in class/Microsoft.SilverlightControls/:
[moon.git] / tools / generators / Generator.cs
blob45f01c49d6d3f1c91abe15da84635af1c8ec74c0
1 /*
2 * Generator.cs
4 * Contact:
5 * Moonlight List (moonlight-list@lists.ximian.com)
7 * Copyright 2008 Novell, Inc. (http://www.novell.com)
9 * See the LICENSE file included with the distribution for details.
12 using System;
13 using System.Linq;
14 using System.Collections.Generic;
15 using System.IO;
16 using System.Text;
19 class Generator {
20 delegate void output_native_type_delegate (string t, string k);
21 static StringBuilder forward_decls = new StringBuilder ();
22 static StringBuilder cbinding_requisites = new StringBuilder ();
24 public void Generate ()
26 GlobalInfo info = GetTypes2 ();
27 //info.Dump (0);
29 GenerateValueH (info);
30 GenerateTypeH (info);
31 GenerateKindCs ();
33 GenerateTypeStaticCpp (info);
34 GenerateCBindings (info);
35 GeneratePInvokes (info);
36 GenerateTypes_G (info);
38 GenerateDPs (info);
39 GenerateManagedDPs (info);
40 GenerateManagedDOs (info);
42 GenerateManagedEvents (info);
44 GenerateJSBindings (info);
47 static void GenerateJSBindings (GlobalInfo all)
49 List<MethodInfo> methods;
50 methods = all.JSMethodsToBind;
51 StringBuilder mappings = new StringBuilder ();
52 StringBuilder header = new StringBuilder ();
53 StringBuilder body = new StringBuilder ();
55 MemberInfo current = null;
56 Dictionary<string, List<MethodInfo>> types = new Dictionary<string, List<MethodInfo>> ();
58 foreach (MemberInfo m in methods) {
59 MethodInfo method = (MethodInfo) m;
60 string name = method.Annotations.GetValue ("GenerateJSBinding");
61 if (name == null)
62 name = method.Name;
63 mappings.AppendLine ("\tMoonId_" + method.Parent.Name + "_" + name + ",");
65 if (current != method.Parent) {
66 current = method.Parent;
68 if (!types.ContainsKey (current.Name))
69 types.Add (current.Name, new List<MethodInfo>());
70 types[current.Name].Add (method);
74 foreach (KeyValuePair<string, List<MethodInfo>> t in types) {
75 string parent = t.Key;
77 header.AppendLine ("/*** Moonlight" + parent + "Class *********/");
79 header.AppendLine ("struct Moonlight" + parent + "Type : MoonlightDependencyObjectType {");
80 header.AppendLine ("\tMoonlight" + parent + "Type ();");
81 header.AppendLine ("};");
82 header.AppendLine ();
83 header.AppendLine ("extern Moonlight" + parent + "Type *Moonlight" + parent + "Class;");
84 header.AppendLine ();
85 header.AppendLine ("struct Moonlight" + parent + "Object : MoonlightDependencyObjectObject {");
86 header.AppendLine ("\tMoonlight" + parent + "Object (NPP instance) : MoonlightDependencyObjectObject (instance)");
87 header.AppendLine ("\t{");
88 header.AppendLine ("\t\tmoonlight_type = Type::" + parent.ToUpper() + ";");
89 header.AppendLine ("\t}");
90 header.AppendLine ();
91 header.AppendLine ("\tvirtual bool Invoke (int id, NPIdentifier name,");
92 header.AppendLine ("\t\tconst NPVariant *args, guint32 argCount, NPVariant *result);");
93 header.AppendLine ();
94 header.AppendLine ("};");
96 body.AppendLine ("/*** Moonlight" + parent + "Class *********/");
97 body.AppendLine ("static NPObject *");
98 body.AppendLine ("moonlight_" + parent.ToLower() + "_allocate (NPP instance, NPClass *klass)");
99 body.AppendLine ("{");
100 body.AppendLine (" return new Moonlight" + parent + "Object (instance);");
101 body.AppendLine ("}");
102 body.AppendLine ();
103 body.AppendLine ("static const MoonNameIdMapping moonlight_" + parent.ToLower() + "_mapping[] = {");
105 for (int i = 0; i < t.Value.Count; i++) {
106 MethodInfo method = t.Value[i];
107 string name = method.Annotations.GetValue ("GenerateJSBinding");
108 if (name == null)
109 name = method.Name;
110 string id = "MoonId_" + parent + "_" + name;
111 body.Append (" {\"" + name.ToLower () + "\", " + id + "}");
113 if (i < t.Value.Count - 1)
114 body.Append (",");
115 body.AppendLine ("");
119 body.AppendLine ("};");
120 body.AppendLine ("");
121 body.AppendLine ("bool");
122 body.AppendLine ("Moonlight" + parent + "Object::Invoke (int id, NPIdentifier name,");
123 body.AppendLine (" const NPVariant *args, guint32 argCount,");
124 body.AppendLine (" NPVariant *result)");
125 body.AppendLine ("{");
126 body.AppendLine (" " + parent + " *dob = (" + parent + "*)GetDependencyObject ();");
127 body.AppendLine ("");
128 body.AppendLine (" switch (id) {");
130 foreach (MethodInfo method in t.Value) {
131 string name = method.Annotations.GetValue ("GenerateJSBinding");
132 if (name == null)
133 name = method.Name;
134 string id = "MoonId_" + parent + "_" + name;
135 body.AppendLine ();
136 body.AppendLine ("\t\tcase " + id + ": {");
138 bool errorcheck = false;
139 string argcodes = "";
140 List<string> args = new List<string>();
141 List<string> parms = new List<string>();
142 for (int i = 0; i < method.Parameters.Count; i++) {
143 ParameterInfo parameter = method.Parameters[i];
145 if (parameter.ParameterType.Value == "MoonError*") {
146 errorcheck = true;
147 } else {
148 argcodes += parameter.ParameterType.GetNPType ();
150 switch (parameter.ParameterType.GetNPType ()) {
151 case "i":
152 args.Add ("\t\t\tint arg" + i + " = NPVARIANT_TO_INT32 (args[" + i + "]);");
153 parms.Add ("arg" + i);
154 break;
155 case "s":
156 args.Add ("\t\t\tchar *arg" + i + " = STRDUP_FROM_VARIANT (args[" + i + "]);");
157 parms.Add ("arg" + i);
158 break;
159 case "o":
160 args.Add ("\t\t\tNPObject *obj" + i + " = NPVARIANT_TO_OBJECT (args[" + i + "]);");
161 args.Add ("\t\t\tif (!npobject_is_dependency_object (obj" + i + "))");
162 args.Add ("\t\t\t\tTHROW_JS_EXCEPTION (\"" + name + "\");");
163 args.Add ("\t\t\tDependencyObject *arg" + i + " = ((MoonlightDependencyObjectObject *) obj" + i + ")->GetDependencyObject();");
164 parms.Add ("(" + parameter.ParameterType.WriteFormatted () + ") arg" + i);
165 break;
166 case "d":
167 args.Add ("\t\t\tdouble arg" + i + " = NPVARIANT_TO_DOUBLE (args[" + i + "]);");
168 parms.Add ("arg" + i);
169 break;
170 case "b":
171 args.Add ("\t\t\tbool arg" + i + " = NPVARIANT_TO_BOOLEAN (args[" + i + "]);");
172 parms.Add ("arg" + i);
173 break;
178 if (argcodes != "") {
179 body.AppendLine ("\t\t\tif (!check_arg_list (\"" + argcodes + "\", argCount, args))");
180 body.AppendLine ("\t\t\t\tTHROW_JS_EXCEPTION (\"" + name + "\");");
183 if (errorcheck) {
184 body.AppendLine ("\t\t\tMoonError err;");
185 parms.Add ("&err");
188 if (args.Count > 0)
189 body.AppendLine (String.Join ("\n", args.ToArray()));
191 body.Append ("\t\t\t");
193 if (method.ReturnType.GetNPType () != "v") {
194 method.ReturnType.WriteFormatted (body);
195 body.AppendLine (" ret = dob->" + method.Name + "(" + String.Join (",", parms.ToArray ()) + ");");
196 } else
197 body.AppendLine ("dob->" + method.Name + "(" + String.Join (",", parms.ToArray ()) + ");");
199 for (int i = 0; i < method.Parameters.Count; i++) {
200 ParameterInfo parameter = method.Parameters[i];
201 if (parameter.ParameterType.GetNPType () == "s")
202 body.AppendLine ("g_free (arg" + i + ");");
205 if (errorcheck)
206 body.AppendLine ("\t\t\tif (err.number != 0) THROW_JS_EXCEPTION (err.message);");
208 switch (method.ReturnType.GetNPType ()) {
209 case "i":
210 body.AppendLine ("\t\t\tINT32_TO_NPVARIANT (ret, *result);");
211 break;
212 case "s":
213 body.AppendLine ("\t\t\tstring_to_npvariant (ret, *result);");
214 break;
215 case "o":
216 body.AppendLine ("\t\t\tif (ret)");
217 body.AppendLine ("\t\t\t\tOBJECT_TO_NPVARIANT (EventObjectCreateWrapper (GetPlugin (), ret), *result);");
218 body.AppendLine ("\t\t\telse");
219 body.AppendLine ("\t\t\t\tNULL_TO_NPVARIANT (*result);");
220 break;
221 case "d":
222 body.AppendLine ("\t\t\tDOUBLE_TO_NPVARIANT (ret, *result);");
223 break;
224 case "b":
225 body.AppendLine ("\t\t\tBOOLEAN_TO_NPVARIANT (ret, *result);");
226 break;
227 case "v":
228 body.AppendLine ("\t\t\tVOID_TO_NPVARIANT (*result);");
229 break;
232 body.AppendLine ("\t\t\treturn true;");
233 body.AppendLine ("\t\t\tbreak;");
234 body.AppendLine ("\t\t}");
237 body.AppendLine ("\t}");
238 body.AppendLine ();
240 body.AppendLine ("\treturn MoonlightDependencyObjectObject::Invoke (id, name, args, argCount, result);");
241 body.AppendLine ("}");
242 body.AppendLine ();
244 body.AppendLine ("Moonlight" + parent + "Type::Moonlight" + parent + "Type ()");
245 body.AppendLine ("{");
246 body.AppendLine (" AddMapping (moonlight_" + parent.ToLower() + "_mapping, G_N_ELEMENTS (moonlight_" + parent.ToLower() + "_mapping));");
247 body.AppendLine ();
248 body.AppendLine (" allocate = moonlight_" + parent.ToLower() + "_allocate;");
249 body.AppendLine ("}");
255 string file = "plugin/plugin-class.h";
257 string contents = File.ReadAllText (file + ".in");
258 contents = contents.Replace ("/*MAP_IDS*/", mappings.ToString());
259 contents = contents.Replace ("/*MAP_HEADERS*/", header.ToString());
261 StringBuilder text = new StringBuilder ();
262 Helper.WriteWarningGenerated (text);
263 contents = text.ToString () + contents;
264 Helper.WriteAllText (file, contents);
266 file = "plugin/plugin-class.g.cpp";
267 contents = File.ReadAllText (file + ".in");
268 contents = contents.Replace ("/*MAP_BODY*/", body.ToString());
270 text = new StringBuilder ();
271 Helper.WriteWarningGenerated (text);
272 contents = text.ToString () + contents;
273 Helper.WriteAllText (file, contents);
276 static void GenerateManagedEvents (GlobalInfo all)
278 string base_dir = Environment.CurrentDirectory;
279 string class_dir = Path.Combine (base_dir, "class");
280 string sys_win_dir = Path.Combine (Path.Combine (class_dir, "System.Windows"), "System.Windows");
281 string filename = Path.Combine (sys_win_dir, "Events.g.cs");
282 string previous_namespace = "";
283 List<TypeInfo> sorted_types = new List<TypeInfo> ();
284 StringBuilder text = new StringBuilder ();
285 Dictionary <TypeInfo, List<FieldInfo>> types = new Dictionary<TypeInfo,List<FieldInfo>> ();
287 foreach (FieldInfo field in all.Events) {
288 TypeInfo parent = field.Parent as TypeInfo;
289 List <FieldInfo> fields;
290 string managed_parent = field.Annotations.GetValue ("ManagedDeclaringType");
292 if (!field.IsEvent || !field.GenerateManagedEvent)
293 continue;
295 if (managed_parent != null) {
296 parent = all.Children [managed_parent] as TypeInfo;
298 if (parent == null)
299 throw new Exception (string.Format ("Could not find the type '{0}' set as ManagedDeclaringType of '{1}'", managed_parent, field.FullName));
302 if (parent == null)
303 throw new Exception (string.Format ("The field '{0}' does not have its parent set.", field.FullName));
305 if (!types.TryGetValue (parent, out fields)) {
306 fields = new List<FieldInfo> ();
307 types.Add (parent, fields);
308 sorted_types.Add (parent);
310 fields.Add (field);
313 Helper.WriteWarningGenerated (text);
314 text.AppendLine ("using Mono;");
315 text.AppendLine ("using System;");
316 text.AppendLine ("using System.Collections.Generic;");
317 text.AppendLine ("using System.Windows;");
318 text.AppendLine ("using System.Windows.Controls;");
319 text.AppendLine ("using System.Windows.Documents;");
320 text.AppendLine ("using System.Windows.Ink;");
321 text.AppendLine ("using System.Windows.Input;");
322 text.AppendLine ("using System.Windows.Markup;");
323 text.AppendLine ("using System.Windows.Media;");
324 text.AppendLine ("using System.Windows.Media.Animation;");
325 text.AppendLine ("using System.Windows.Shapes;");
326 text.AppendLine ();
328 text.AppendLine ("namespace Mono {");
329 text.AppendLine ("\tinternal class EventIds {");
330 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
331 if (t.GetEventCount () == 0)
332 continue;
335 foreach (FieldInfo field in t.Events) {
336 text.Append ("\t\tpublic const int ");
337 text.Append (t.Name);
338 text.Append ("_");
339 text.Append (field.EventName);
340 text.Append ("Event = ");
341 text.Append (t.GetEventId (field));
342 text.AppendLine (";");
345 text.AppendLine ("\t}");
347 text.AppendLine ("\tinternal partial class Events {");
348 text.AppendLine ("\t\tpublic static UnmanagedEventHandler CreateDispatcherFromEventId (int eventId, Delegate value) {");
349 text.AppendLine ("\t\t\tswitch (eventId) {");
351 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
352 if (t.GetEventCount () == 0)
353 continue;
356 foreach (FieldInfo field in t.Events) {
357 if (field.GenerateManagedEventField == false)
358 continue;
359 text.Append ("\t\t\t\tcase EventIds.");
360 text.Append (t.Name);
361 text.Append ("_");
362 text.Append (field.EventName);
363 text.Append ("Event: return Events.");
365 text.Append (GetDispatcherMethodName(field.EventDelegateType));
366 text.Append (" ((");
367 text.Append (field.EventDelegateType);
368 text.Append (") value)");
369 text.AppendLine (";");
372 text.AppendLine ("\t\t\t\tdefault: throw new NotSupportedException ();");
373 text.AppendLine ("\t\t\t}");
374 text.AppendLine ("\t\t}");
375 text.AppendLine ("\t}");
377 text.AppendLine ("}");
379 sorted_types.Sort (new Members.MembersSortedByManagedFullName <TypeInfo> ());
380 for (int i = 0; i < sorted_types.Count; i++) {
381 TypeInfo type = sorted_types [i];
382 List<FieldInfo> fields = types [type];
383 TypeInfo parent = type;
384 string ns;
386 ns = parent.Namespace;
388 if (string.IsNullOrEmpty (ns)) {
389 Console.WriteLine ("The type '{0}' in {1} does not have a namespace annotation.", parent.FullName, parent.Header);
390 continue;
393 if (type.Annotations.ContainsKey ("ManagedEvents")) {
394 string event_mode = type.Annotations.GetValue ("ManagedEvents");
395 switch (event_mode) {
396 case "None":
397 case "Manual":
398 continue;
399 case "Generate":
400 break;
401 default:
402 throw new Exception (string.Format ("Invalid value '{0}' for ManagedEvents in '{1}'", event_mode, type.FullName));
406 if (ns == "None") {
407 Console.WriteLine ("'{0}''s Namespace = 'None', this type should have set @ManagedEvents=Manual to not create events.", type.FullName);
408 continue;
411 string check_ns = Path.Combine (Path.Combine (Path.Combine (class_dir, "System.Windows"), ns), parent.Name + ".cs");
412 if (!File.Exists (check_ns))
413 Console.WriteLine ("The file {0} does not exist, did you annotate the class with the wrong namespace?", check_ns);
415 if (previous_namespace != ns) {
416 if (previous_namespace != string.Empty) {
417 text.AppendLine ("}");
418 text.AppendLine ();
420 text.Append ("namespace ");
421 text.Append (ns);
422 text.AppendLine (" {");
423 previous_namespace = ns;
424 } else {
425 text.AppendLine ();
427 text.Append ("\tpartial class ");
428 text.Append (parent.ManagedName);
429 text.AppendLine (" {");
431 fields.Sort (new Members.MembersSortedByName <FieldInfo> ());
434 foreach (FieldInfo field in fields) {
435 if (!field.IsEvent)
436 continue;
438 text.AppendLine ();
440 // property accessor
441 text.Append ("\t\t");
442 Helper.WriteAccess (text, field.GetManagedAccessorAccess ());
443 text.Append (" event ");
444 text.Append (field.EventDelegateType);
445 text.Append (" ");
446 text.Append (field.EventName);
447 text.AppendLine (" {");
449 // property getter
450 text.Append ("\t\t\t");
451 if (field.GetManagedAccessorAccess () != field.GetManagedGetterAccess ()) {
452 Helper.WriteAccess (text, field.GetManagedGetterAccess ());
453 text.Append (" ");
456 text.Append ("add { RegisterEvent (EventIds.");
457 text.Append (field.ParentType.Name);
458 text.Append ("_");
459 text.Append (field.EventName);
460 text.Append ("Event, value, Events.");
461 text.Append (GetDispatcherMethodName(field.EventDelegateType));
462 text.Append (" (value)");
463 text.AppendLine ("); }");
465 text.Append ("\t\t\t");
466 text.Append ("remove { UnregisterEvent (EventIds.");
467 text.Append (field.ParentType.Name);
468 text.Append ("_");
469 text.Append (field.EventName);
470 text.Append ("Event, value);");
471 text.AppendLine (" }");
473 text.AppendLine ("\t\t}");
475 if (field.GenerateManagedEventField) {
476 text.Append ("\t\t");
477 text.Append (string.Format ("public static readonly RoutedEvent {0}Event = new RoutedEvent (EventIds.{1}_{2}Event);", field.EventName, field.ParentType.Name, field.EventName));
478 text.AppendLine ();
482 text.AppendLine ("\t}");
485 text.AppendLine ("}");
487 Helper.WriteAllText (filename, text.ToString ());
490 static string GetDispatcherMethodName (string delegateType)
492 if (delegateType.Contains ("<")) {
493 string[] delegate_types = delegateType.Split ('<', '>');
494 return string.Format ("Create{0}{1}Dispatcher", delegate_types[1], delegate_types[0]);
496 else
497 return string.Format ("Create{0}Dispatcher", delegateType);
500 static void GenerateManagedDOs (GlobalInfo all)
502 string base_dir = Environment.CurrentDirectory;
503 string class_dir = Path.Combine (base_dir, "class");
504 string sys_win_dir = Path.Combine (Path.Combine (class_dir, "System.Windows"), "System.Windows");
505 string filename = Path.Combine (sys_win_dir, "DependencyObject.g.cs");
506 string previous_namespace = "";
507 StringBuilder text = new StringBuilder ();
508 List<TypeInfo> types = all.GetDependencyObjects ();
510 Helper.WriteWarningGenerated (text);
511 text.AppendLine ("using Mono;");
512 text.AppendLine ("using System;");
513 text.AppendLine ("using System.Collections.Generic;");
514 text.AppendLine ("using System.Windows;");
515 text.AppendLine ("using System.Windows.Controls;");
516 text.AppendLine ("using System.Windows.Documents;");
517 text.AppendLine ("using System.Windows.Ink;");
518 text.AppendLine ("using System.Windows.Input;");
519 text.AppendLine ("using System.Windows.Markup;");
520 text.AppendLine ("using System.Windows.Media;");
521 text.AppendLine ("using System.Windows.Media.Animation;");
522 text.AppendLine ("using System.Windows.Shapes;");
523 text.AppendLine ();
525 for (int i = 0; i < types.Count; i++) {
526 TypeInfo type = types [i];
527 bool call_initialize = type.Annotations.ContainsKey ("CallInitialize");
528 string ns;
530 ns = type.Namespace;
532 if (string.IsNullOrEmpty (ns)) {
533 Console.WriteLine ("The type '{0}' in {1} does not have a namespace annotation.", type.FullName, Path.GetFileName (type.Header));
534 continue;
537 if (ns == "None") {
538 //Console.WriteLine ("The type '{0}''s Namespace annotation is 'None'.", type.FullName);
539 continue;
542 string check_ns = Path.Combine (Path.Combine (Path.Combine (class_dir, "System.Windows"), ns), type.ManagedName.Replace ("`1", "") + ".cs");
543 if (!File.Exists (check_ns)) {
544 Console.WriteLine ("The file {0} does not exist, did you annotate the class with the wrong namespace?", check_ns);
545 continue;
548 if (previous_namespace != ns) {
549 if (previous_namespace != string.Empty) {
550 text.AppendLine ("}");
551 text.AppendLine ();
553 text.Append ("namespace ");
554 text.Append (ns);
555 text.AppendLine (" {");
556 previous_namespace = ns;
557 } else {
558 text.AppendLine ();
561 if (type.ContentProperty != null)
562 text.AppendFormat ("\t[ContentProperty (\"{0}\")]\n", type.ContentProperty);
563 text.Append ("\tpartial class ");
564 text.Append (type.ManagedName.Replace ("`1", "<T>"));
565 text.AppendLine (" {");
567 // Public ctor
568 if (!string.IsNullOrEmpty (type.C_Constructor)) {
569 string access = "Public";
570 foreach (MemberInfo member in type.Children.Values) {
571 MethodInfo method = member as MethodInfo;
573 if (method == null || !method.IsConstructor || method.IsStatic)
574 continue;
576 if (method.Parameters.Count != 0)
577 continue;
579 if (method.Annotations.ContainsKey ("ManagedAccess"))
580 access = method.Annotations.GetValue ("ManagedAccess");
581 break;
585 text.Append ("\t\t");
586 Helper.WriteAccess (text, access);
587 text.Append (" ");
588 text.Append (type.ManagedName.Replace ("`1", ""));
589 text.Append (" () : base (NativeMethods.");
590 text.Append (type.C_Constructor);
591 text.Append (" (), true)");
592 if (call_initialize) {
593 text.AppendLine ();
594 text.AppendLine ("\t\t{");
595 text.AppendLine ("\t\t\tInitialize ();");
596 text.AppendLine ("\t\t}");
597 } else {
598 text.AppendLine (" {}");
602 // Internal ctor
603 text.Append ("\t\tinternal ");
604 text.Append (type.ManagedName.Replace ("`1", ""));
605 text.Append (" (IntPtr raw, bool dropref) : base (raw, dropref)");
606 if (call_initialize) {
607 text.AppendLine ();
608 text.AppendLine ("\t\t{");
609 text.AppendLine ("\t\t\tInitialize ();");
610 text.AppendLine ("\t\t}");
611 } else {
612 text.AppendLine (" {}");
615 text.AppendLine ("\t}");
617 text.AppendLine ("}");
619 Helper.WriteAllText (filename, text.ToString ());
622 static void GenerateManagedDPs (GlobalInfo all)
624 string base_dir = Environment.CurrentDirectory;
625 string class_dir = Path.Combine (base_dir, "class");
626 string sys_win_dir = Path.Combine (Path.Combine (class_dir, "System.Windows"), "System.Windows");
627 string filename = Path.Combine (sys_win_dir, "DependencyProperty.g.cs");
628 string previous_namespace = "";
629 List<TypeInfo> sorted_types = new List<TypeInfo> ();
630 StringBuilder text = new StringBuilder ();
631 Dictionary <TypeInfo, List<FieldInfo>> types = new Dictionary<TypeInfo,List<FieldInfo>> ();
633 foreach (FieldInfo field in all.DependencyProperties) {
634 TypeInfo parent = field.Parent as TypeInfo;
635 List <FieldInfo> fields;
636 string managed_parent = field.Annotations.GetValue ("ManagedDeclaringType");
638 if (field.Annotations.GetValue ("GenerateManagedDP") == "false")
639 continue;
641 if (managed_parent != null) {
642 parent = all.Children [managed_parent] as TypeInfo;
644 if (parent == null)
645 throw new Exception (string.Format ("Could not find the type '{0}' set as ManagedDeclaringType of '{1}'", managed_parent, field.FullName));
648 if (parent == null)
649 throw new Exception (string.Format ("The field '{0}' does not have its parent set.", field.FullName));
651 if (!types.TryGetValue (parent, out fields)) {
652 fields = new List<FieldInfo> ();
653 types.Add (parent, fields);
654 sorted_types.Add (parent);
656 fields.Add (field);
659 Helper.WriteWarningGenerated (text);
660 text.AppendLine ("using Mono;");
661 text.AppendLine ("using System;");
662 text.AppendLine ("using System.Collections.Generic;");
663 text.AppendLine ("using System.Windows;");
664 text.AppendLine ("using System.Windows.Controls;");
665 text.AppendLine ("using System.Windows.Documents;");
666 text.AppendLine ("using System.Windows.Ink;");
667 text.AppendLine ("using System.Windows.Input;");
668 text.AppendLine ("using System.Windows.Markup;");
669 text.AppendLine ("using System.Windows.Media;");
670 text.AppendLine ("using System.Windows.Media.Animation;");
671 text.AppendLine ("using System.Windows.Media.Effects;");
672 text.AppendLine ("using System.Windows.Shapes;");
673 text.AppendLine ();
675 sorted_types.Sort (new Members.MembersSortedByManagedFullName <TypeInfo> ());
676 for (int i = 0; i < sorted_types.Count; i++) {
677 TypeInfo type = sorted_types [i];
678 List<FieldInfo> fields = types [type];
679 TypeInfo parent = type;
680 string ns;
682 ns = parent.Namespace;
684 if (string.IsNullOrEmpty (ns)) {
685 Console.WriteLine ("The type '{0}' in {1} does not have a namespace annotation.", parent.FullName, parent.Header);
686 continue;
689 if (type.Annotations.ContainsKey ("ManagedDependencyProperties")) {
690 string dp_mode = type.Annotations.GetValue ("ManagedDependencyProperties");
691 switch (dp_mode) {
692 case "None":
693 case "Manual":
694 continue;
695 case "Generate":
696 break;
697 default:
698 throw new Exception (string.Format ("Invalid value '{0}' for ManagedDependencyProperties in '{1}'", dp_mode, type.FullName));
702 if (ns == "None") {
703 Console.WriteLine ("'{0}''s Namespace = 'None', this type should have set @ManagedDependencyProperties=Manual to not create DPs.", type.FullName);
704 continue;
707 string check_ns = Path.Combine (Path.Combine (Path.Combine (class_dir, "System.Windows"), ns), parent.Name + ".cs");
708 if (!File.Exists (check_ns))
709 Console.WriteLine ("The file {0} does not exist, did you annotate the class with the wrong namespace?", check_ns);
711 if (previous_namespace != ns) {
712 if (previous_namespace != string.Empty) {
713 text.AppendLine ("}");
714 text.AppendLine ();
716 text.Append ("namespace ");
717 text.Append (ns);
718 text.AppendLine (" {");
719 previous_namespace = ns;
720 } else {
721 text.AppendLine ();
723 text.Append ("\tpartial class ");
724 text.Append (parent.ManagedName);
725 text.AppendLine (" {");
727 fields.Sort (new Members.MembersSortedByName <FieldInfo> ());
729 // The DP registration
730 foreach (FieldInfo field in fields) {
731 bool conv_int_to_double = field.GetDPManagedPropertyType (all) == "int" && field.GetDPPropertyType (all).Name == "double";
733 text.Append ("\t\t");
734 Helper.WriteAccess (text, field.GetManagedFieldAccess ());
735 text.Append (" static readonly DependencyProperty ");
736 text.Append (field.Name);
737 text.Append (" = DependencyProperty.Lookup (Kind.");
738 text.Append (field.ParentType.KindName);
739 text.Append (", \"");
740 text.Append (field.GetDependencyPropertyName ());
741 text.Append ("\", typeof (");
742 if (conv_int_to_double)
743 text.Append ("double");
744 else
745 text.Append (field.GetDPManagedPropertyType (all));
746 text.AppendLine ("));");
749 foreach (FieldInfo field in fields) {
750 bool conv_int_to_double = field.GetDPManagedPropertyType (all) == "int" && field.GetDPPropertyType (all).Name == "double";
752 if (field.IsDPAttached || !field.GenerateManagedAccessors)
753 continue;
755 text.AppendLine ();
757 // property accessor
758 text.Append ("\t\t");
759 Helper.WriteAccess (text, field.GetManagedAccessorAccess ());
760 text.Append (" ");
761 text.Append (field.GetDPManagedPropertyType (all));
762 text.Append (" ");
763 text.Append (field.GetDependencyPropertyName ());
764 text.AppendLine (" {");
766 // property getter
767 text.Append ("\t\t\t");
768 if (field.GetManagedAccessorAccess () != field.GetManagedGetterAccess ()) {
769 Helper.WriteAccess (text, field.GetManagedGetterAccess ());
770 text.Append (" ");
773 text.Append ("get { return (");
774 text.Append (field.GetDPManagedPropertyType (all));
775 if (conv_int_to_double)
776 text.Append (") (double");
777 text.Append (") GetValue (");
778 text.Append (field.Name);
779 text.AppendLine ("); }");
781 // property setter
782 if (!field.IsDPReadOnly) {
783 text.Append ("\t\t\t");
784 if (field.GetManagedAccessorAccess () != field.GetManagedSetterAccess ()) {
785 Helper.WriteAccess (text, field.GetManagedSetterAccess ());
786 text.Append (" ");
788 text.Append ("set { SetValue (");
789 text.Append (field.Name);
790 text.AppendLine (", value); }");
792 text.AppendLine ("\t\t}");
795 text.AppendLine ("\t}");
797 text.AppendLine ("}");
799 Helper.WriteAllText (filename, text.ToString ());
802 class TypeEdgeCount {
803 public TypeEdgeCount (TypeInfo type)
805 Type = type;
806 Inbound = new List<TypeInfo>();
807 Outbound = new List<TypeInfo>();
810 public TypeInfo Type {
811 get; private set;
813 public List<TypeInfo> Inbound {
814 get; private set;
816 public List<TypeInfo> Outbound {
817 get; private set;
821 static List<FieldInfo> TopoSortedProperties (GlobalInfo all, List<TypeInfo> types)
823 Dictionary<TypeInfo,TypeEdgeCount> typeHash = new Dictionary<TypeInfo,TypeEdgeCount>();
825 List<TypeInfo> remainingTypes = new List<TypeInfo>();
827 foreach (TypeInfo type in types) {
828 typeHash.Add (type, new TypeEdgeCount (type));
829 remainingTypes.Add (type);
832 // build up edges for our graph
833 foreach (TypeInfo type in typeHash.Keys) {
835 // every property defines an edge from the declaring type to the property type
836 foreach (FieldInfo prop in type.Properties) {
837 if (string.IsNullOrEmpty (prop.DPDefaultValue))
838 continue;
840 TypeInfo propType = prop.GetDPPropertyType (all);
841 if (propType == type)
842 continue;
843 if (typeHash.ContainsKey (propType) && !typeHash[propType].Inbound.Contains (type)) {
844 typeHash[propType].Inbound.Add (type);
845 typeHash[type].Outbound.Add (propType);
849 // every base class has an edge to subclass
850 // (this is kind of a hack to deal with
851 // property types which are listed as base
852 // types when the default values are
853 // subclasses.
855 TypeInfo ourType = type;
856 TypeReference baseRef = ourType.Base;
857 while (baseRef != null && !string.IsNullOrEmpty (baseRef.Value)) {
858 TypeInfo baseType = (TypeInfo) all.Children [baseRef.Value];
859 if (baseType == null)
860 break;
861 if (typeHash.ContainsKey (baseType) && !typeHash[baseType].Outbound.Contains (ourType)) {
862 typeHash[baseType].Outbound.Add (ourType);
863 typeHash[ourType].Inbound.Add (baseType);
865 ourType = baseType;
866 if (!typeHash.ContainsKey (ourType))
867 break;
868 baseRef = ourType.Base;
872 List<TypeInfo> sorted = new List<TypeInfo>();
873 List<TypeInfo> roots = new List<TypeInfo>();
875 foreach (TypeEdgeCount tec in typeHash.Values) {
876 if (tec.Inbound.Count == 0)
877 roots.Add (tec.Type);
880 while (roots.Count > 0) {
881 TypeInfo type = roots[0];
882 roots.RemoveAt (0);
884 sorted.Add (type);
885 remainingTypes.Remove (type);
887 foreach (TypeInfo targetType in typeHash[type].Outbound) {
888 if (!typeHash.ContainsKey (targetType))
889 continue;
890 typeHash[targetType].Inbound.Remove (type);
891 if (typeHash[targetType].Inbound.Count == 0) {
892 roots.Add (targetType);
897 if (remainingTypes.Count > 0) {
898 throw new Exception (string.Format ("cycle in the DO/DP graph ({0} types left)", remainingTypes.Count));
901 List<FieldInfo> fields = new List<FieldInfo>();
902 foreach (TypeInfo type in sorted) {
903 foreach (FieldInfo field in type.Properties)
904 fields.Insert (0, field);
906 return fields;
909 static void GenerateDPs (GlobalInfo all)
911 string base_dir = Environment.CurrentDirectory;
912 string moon_dir = Path.Combine (base_dir, "src");
913 // int version_previous = 0;
914 StringBuilder text = new StringBuilder ();
915 List<FieldInfo> fields = all.DependencyProperties;
916 List<string> headers = new List<string> ();
918 List<TypeInfo> types = new List<TypeInfo> ();
919 foreach (FieldInfo field in fields) {
920 if (!types.Contains ((TypeInfo)field.Parent))
921 types.Add ((TypeInfo)field.Parent);
923 fields = TopoSortedProperties (all, types);
925 headers.Add ("dependencyproperty.h");
926 headers.Add ("validators.h");
927 headers.Add ("provider.h");
928 headers.Add ("color.h");
929 foreach (FieldInfo field in fields) {
930 string h;
931 if (string.IsNullOrEmpty (field.Header))
932 continue;
933 h = Path.GetFileName (field.Header);
935 if (!headers.Contains (h))
936 headers.Add (h);
939 Helper.WriteWarningGenerated (text);
940 text.AppendLine ();
941 text.AppendLine ("#include <config.h>");
942 text.AppendLine ();
943 headers.Sort ();
944 foreach (string h in headers) {
945 text.Append ("#include \"");
946 text.Append (h);
947 text.AppendLine ("\"");
949 text.AppendLine ();
950 text.AppendLine ("void");
951 text.AppendLine ("Types::RegisterNativeProperties ()");
952 text.AppendLine ("{");
954 for (int i = 0; i < fields.Count; i++) {
955 FieldInfo field = fields [i];
956 TypeInfo type = field.ParentType;
957 TypeInfo propertyType = null;
958 string default_value = field.DPDefaultValue;
959 bool has_default_value = !string.IsNullOrEmpty (default_value);
960 string autocreator = field.DPAutoCreator;
961 bool is_nullable = field.IsDPNullable;
962 bool is_attached = field.IsDPAttached;
963 bool is_readonly = field.IsDPReadOnly;
964 bool is_always_change = field.IsDPAlwaysChange;
965 string validator = field.DPValidator;
966 bool is_full = is_attached || is_readonly || is_always_change || validator != null || autocreator != null || is_nullable;
968 propertyType = field.GetDPPropertyType (all);
970 text.Append ("\t");
972 if (propertyType == null) {
973 text.Append ("// (no PropertyType was found for this DependencyProperty) ");
974 } else {
975 headers.Add (propertyType.Header);
978 text.Append ("DependencyProperty::Register");
979 if (is_full)
980 text.Append ("Full");
982 text.Append (" (");
983 text.Append ("this, ");
984 text.Append ("Type::");
985 text.Append (type.KindName);
986 text.Append (", \"");
988 text.Append (field.GetDependencyPropertyName ());
989 text.Append ("\"");
990 text.Append (", ");
992 text.Append (field.IsCustom ? "true" : "false");
993 text.Append (", ");
995 if (is_full) {
996 if (has_default_value) {
997 if (default_value.StartsWith ("new "))
998 text.Append ("Value::CreateUnrefPtr (");
999 else
1000 text.Append ("new Value (");
1001 text.Append (default_value);
1002 text.Append (")");
1003 } else {
1004 text.Append ("NULL");
1006 } else {
1007 if (has_default_value) {
1008 if (default_value.StartsWith ("new "))
1009 text.Append ("Value::CreateUnrefPtr (");
1010 else
1011 text.Append ("new Value (");
1012 text.Append (default_value);
1013 text.Append (")");
1017 if ((has_default_value || is_full))
1018 text.Append (", ");
1020 if (propertyType != null) {
1021 if (propertyType.IsEnum) {
1022 text.Append ("Type::INT32");
1023 } else {
1024 text.Append ("Type::");
1025 text.Append (propertyType.KindName);
1027 } else if (!has_default_value) {
1028 text.Append ("Type::INVALID");
1029 Console.WriteLine ("{0} does not define its property type.", field.FullName);
1032 if (is_full) {
1033 text.Append (", ");
1034 text.Append (is_attached ? "true" : "false");
1035 text.Append (", ");
1036 text.Append (is_readonly ? "true" : "false");
1037 text.Append (", ");
1038 text.Append (is_always_change ? "true" : "false");
1039 text.Append (", ");
1040 text.Append ("NULL");
1041 text.Append (", ");
1042 text.Append (validator != null ? ("Validators::" + validator) : "NULL");
1043 text.Append (", ");
1044 text.Append (autocreator != null
1045 ? (autocreator.Contains("::") ? autocreator : "AutoCreators::" + autocreator)
1046 : "NULL");
1047 text.Append (", ");
1048 text.Append (is_nullable ? "true" : "false");
1051 text.AppendLine (");");
1053 text.AppendLine ("}");
1054 text.AppendLine ();
1056 // Static initializers
1057 for (int i = 0; i < fields.Count; i++) {
1058 FieldInfo field = fields [i];
1059 text.Append ("const int ");
1060 text.Append (field.Parent.Name);
1061 text.Append ("::");
1062 text.Append (field.Name);
1063 text.Append (" = ");
1064 text.Append (i);
1065 text.AppendLine (";");
1067 text.AppendLine ();
1069 // C++ Accessors
1070 for (int i = 0; i < fields.Count; i++) {
1071 FieldInfo field = fields [i];
1072 TypeInfo prop_type;
1073 string prop_type_str;
1074 string value_str;
1075 string prop_default = null;
1076 bool both = field.Annotations.ContainsKey ("GenerateAccessors");
1077 bool setter = both || field.Annotations.ContainsKey ("GenerateSetter");
1078 bool getter = both || field.Annotations.ContainsKey ("GenerateGetter");
1079 bool is_attached = field.IsDPAttached;
1080 bool nullable_setter = setter && field.IsDPNullable;
1081 bool doing_nullable_setter = false;
1083 if (!setter && !getter)
1084 continue;
1086 prop_type = field.GetDPPropertyType (all);
1088 switch (prop_type.Name) {
1089 case "char*":
1090 prop_type_str = "const char *";
1091 value_str = "String";
1092 break;
1093 case "int":
1094 case "gint32":
1095 value_str = "Int32";
1096 prop_type_str = prop_type.Name;
1097 prop_default = "0";
1098 break;
1099 case "double":
1100 value_str = "Double";
1101 prop_type_str = prop_type.Name;
1102 prop_default = "0.0";
1103 break;
1104 case "bool":
1105 prop_type_str = prop_type.Name;
1106 value_str = "Bool";
1107 prop_default = "false";
1108 break;
1109 case "char":
1110 prop_type_str = "gunichar";
1111 value_str = "Char";
1112 prop_default = "0";
1113 break;
1114 case "object":
1115 prop_type_str = "Value *";
1116 prop_default = "NULL";
1117 value_str = null;
1118 break;
1119 default:
1120 prop_type_str = prop_type.Name;
1121 value_str = prop_type.Name;
1122 break;
1125 string GetterName = string.Format ("{0}::Get{1}", field.ParentType.Name, field.GetDependencyPropertyName());
1126 string SetterName = string.Format ("{0}::Set{1}", field.ParentType.Name, field.GetDependencyPropertyName());
1128 if (getter) {
1129 text.Append (prop_type_str);
1130 if (field.IsDPNullable || (prop_type.IsClass || prop_type.IsStruct))
1131 text.Append (" *");
1132 text.AppendLine ();
1133 text.Append (GetterName);
1134 if (is_attached)
1135 text.AppendLine (" (DependencyObject *obj)");
1136 else
1137 text.AppendLine (" ()");
1138 text.AppendLine ("{");
1141 if (value_str == null) {
1142 text.Append ("\treturn ");
1143 } else if (is_attached) {
1144 text.Append ("\tValue *value = (!obj) ? NULL : ");
1145 } else {
1146 text.Append ("\tValue *value = ");
1149 text.AppendFormat ("{0}{1}GetValue ({2}::{3});\n",
1150 is_attached ? "obj->" : "",
1151 field.ParentType.NeedsQualifiedGetValue(all) ? "DependencyObject::" : "",
1152 field.ParentType.Name, field.Name);
1154 if (is_attached) {
1155 text.AppendFormat ("\tif (!value) value = Deployment::GetCurrent ()->GetTypes ()->GetProperty ({0}::{1})->GetDefaultValue();\n",
1156 field.ParentType.Name, field.Name);
1159 if (value_str == null) {
1160 // Skip this
1161 } else if (field.IsDPNullable || (prop_type.IsClass || prop_type.IsStruct || prop_type.Name == "char*")) {
1162 text.Append ("\treturn value ? ");
1163 if (prop_type.IsEnum) {
1164 text.AppendFormat ("({0}) value->AsInt32() : ({0}) 0", prop_type.Name);
1165 } else {
1166 if (!field.IsDPNullable && (/*prop_type.IsStruct || */prop_default != null))
1167 if (string.IsNullOrEmpty (prop_default))
1168 throw new NotImplementedException (
1169 string.Format ("Generation of DependencyProperties with struct values ({0}.{1})",
1170 field.ParentType.Name, field.Name));
1172 text.AppendFormat ("value->As{0}{1} () : {2}",
1173 field.IsDPNullable && !(prop_type.IsStruct || prop_type.IsClass) ? "Nullable" : "",
1174 value_str,
1175 !field.IsDPNullable && prop_default != null ? prop_default : "NULL");
1177 } else {
1178 // Value cannot be null, so don't need to check for it
1179 text.Append ("\treturn ");
1180 if (prop_type.IsEnum) {
1181 text.AppendFormat ("({0}) value->AsInt32 ()", prop_type.Name);
1182 } else {
1183 text.AppendFormat ("value->As{0} ()", value_str);
1187 if (value_str != null)
1188 text.AppendLine (";");
1189 text.AppendLine ("}");
1190 text.AppendLine ();
1193 do_nullable_setter:
1194 if (setter) {
1195 text.AppendLine ("void");
1196 text.Append (SetterName);
1197 text.Append (" (");
1198 if (is_attached)
1199 text.Append ("DependencyObject *obj, ");
1200 text.Append (prop_type_str);
1201 if (prop_type.Name != "char*")
1202 text.Append (' ');
1203 if (!nullable_setter && (prop_type.IsClass || prop_type.IsStruct))
1204 text.Append ('*');
1205 text.AppendLine ("value)");
1207 text.AppendLine ("{");
1208 if (is_attached)
1209 text.AppendLine ("\tif (!obj) return;");
1210 if (doing_nullable_setter) {
1211 text.AppendLine ("\tif (!value)");
1212 text.Append ("\t\t");
1213 text.AppendFormat ("{0}{1}SetValue ({2}::{3}, NULL);\n",
1214 is_attached ? "obj->" : "",
1215 field.ParentType.NeedsQualifiedGetValue(all) ? "DependencyObject::" : "",
1216 field.ParentType.Name, field.Name);
1217 text.AppendLine ("\telse");
1218 text.Append ("\t\t");
1219 text.AppendFormat ("{0}{1}SetValue ({2}::{3}, Value (*value));\n",
1220 is_attached ? "obj->" : "",
1221 field.ParentType.NeedsQualifiedGetValue(all) ? "DependencyObject::" : "",
1222 field.ParentType.Name, field.Name);
1223 } else {
1224 if (!nullable_setter && prop_type.IsStruct)
1225 text.AppendLine ("\tif (!value) return;");
1226 text.Append ("\t");
1227 text.AppendFormat ("{0}{1}SetValue ({2}::{3}, ",
1228 is_attached ? "obj->" : "",
1229 field.ParentType.NeedsQualifiedGetValue(all) ? "DependencyObject::" : "",
1230 field.ParentType.Name, field.Name);
1232 if (prop_type.Name == "guint64" || prop_type.Name == "TimeSpan") {
1233 text.AppendFormat ("Value (value, Type::{0}));\n",
1234 prop_type.KindName);
1236 else if (prop_type.Name == "char") {
1237 text.AppendLine ("Value (value, Type::CHAR));");
1239 else if ((value_str == null) || (!nullable_setter && prop_type.IsStruct)) {
1240 text.AppendLine ("Value (*value));");
1242 else if (prop_type.IsClass) {
1243 text.AppendLine ("Value::CreateUnrefPtr (value));");
1245 else {
1246 text.AppendLine ("Value (value));");
1249 text.AppendLine ("}");
1250 text.AppendLine ();
1253 if (nullable_setter) {
1254 if (!prop_type.IsStruct)
1255 prop_type_str += " *";
1256 nullable_setter = false;
1257 doing_nullable_setter = true;
1258 goto do_nullable_setter;
1262 Helper.WriteAllText (Path.Combine (moon_dir, "dependencyproperty.g.cpp"), text.ToString ());
1266 static GlobalInfo GetTypes2 ()
1268 string srcdir = Path.Combine (Environment.CurrentDirectory, "src");
1269 string asfdir = Path.Combine (srcdir, "asf");
1270 string plugindir = Path.Combine (Environment.CurrentDirectory, "plugin");
1271 List<string> all_files = new List<string> ();
1273 all_files.AddRange (Directory.GetFiles (srcdir, "*.h"));
1274 all_files.AddRange (Directory.GetFiles (asfdir, "*.h"));
1275 all_files.AddRange (Directory.GetFiles (plugindir, "*.h"));
1277 RemoveExcludedSrcFiles (srcdir, all_files);
1279 Tokenizer tokenizer = new Tokenizer (all_files.ToArray ());
1280 GlobalInfo all = new GlobalInfo ();
1282 tokenizer.Advance (false);
1284 try {
1285 while (ParseMembers (all, tokenizer)) {
1287 } catch (Exception ex) {
1288 throw new Exception (string.Format ("{0}({1}): {2}", tokenizer.CurrentFile, tokenizer.CurrentLine, ex.Message), ex);
1291 // Add all the manual types
1292 TypeInfo t;
1293 TypeInfo IComparableInfo;
1294 TypeInfo IFormattableInfo;
1295 TypeInfo IConvertibleInfo;
1296 TypeInfo IEquatableBoolInfo;
1297 TypeInfo IComparableBoolInfo;
1298 TypeInfo IEquatableDoubleInfo;
1299 TypeInfo IComparableDoubleInfo;
1300 TypeInfo IEquatableFloatInfo;
1301 TypeInfo IComparableFloatInfo;
1302 TypeInfo IEquatableCharInfo;
1303 TypeInfo IComparableCharInfo;
1304 TypeInfo IEquatableIntInfo;
1305 TypeInfo IComparableIntInfo;
1306 TypeInfo IEquatableLongInfo;
1307 TypeInfo IComparableLongInfo;
1308 TypeInfo IEquatableStringInfo;
1309 TypeInfo IComparableStringInfo;
1310 TypeInfo IEquatableTimeSpanInfo;
1311 TypeInfo IComparableTimeSpanInfo;
1312 TypeInfo IEquatableUintInfo;
1313 TypeInfo IComparableUintInfo;
1314 TypeInfo IEquatableUlongInfo;
1315 TypeInfo IComparableUlongInfo;
1317 all.Children.Add (new TypeInfo ("object", "OBJECT", "INVALID", true, true));
1319 all.Children.Add (IComparableInfo = new TypeInfo ("IComparable", "ICOMPARABLE", "OBJECT", true, true, false, true));
1320 all.Children.Add (IFormattableInfo = new TypeInfo ("IFormattable", "IFORMATTABLE", "OBJECT", true, true, false, true));
1321 all.Children.Add (IConvertibleInfo = new TypeInfo ("IConvertible", "ICONVERTIBLE", "OBJECT", true, true, false, true));
1323 all.Children.Add (IEquatableBoolInfo = new TypeInfo ("IEquatable<bool>", "IEQUATABLE_BOOL", "OBJECT", true, true, false, true));
1324 all.Children.Add (IComparableBoolInfo = new TypeInfo ("IComparable<bool>", "ICOMPARABLE_BOOL", "OBJECT", true, true, false, true));
1326 all.Children.Add (IEquatableDoubleInfo = new TypeInfo ("IEquatable<double>", "IEQUATABLE_DOUBLE", "OBJECT", true, true, false, true));
1327 all.Children.Add (IComparableDoubleInfo = new TypeInfo ("IComparable<double>", "ICOMPARABLE_DOUBLE", "OBJECT", true, true, false, true));
1329 all.Children.Add (IEquatableFloatInfo = new TypeInfo ("IEquatable<float>", "IEQUATABLE_FLOAT", "OBJECT", true, true, false, true));
1330 all.Children.Add (IComparableFloatInfo = new TypeInfo ("IComparable<float>", "ICOMPARABLE_FLOAT", "OBJECT", true, true, false, true));
1332 all.Children.Add (IEquatableCharInfo = new TypeInfo ("IEquatable<char>", "IEQUATABLE_CHAR", "OBJECT", true, true, false, true));
1333 all.Children.Add (IComparableCharInfo = new TypeInfo ("IComparable<char>", "ICOMPARABLE_CHAR", "OBJECT", true, true, false, true));
1335 all.Children.Add (IEquatableIntInfo = new TypeInfo ("IEquatable<int>", "IEQUATABLE_INT", "OBJECT", true, true, false, true));
1336 all.Children.Add (IComparableIntInfo = new TypeInfo ("IComparable<int>", "ICOMPARABLE_INT", "OBJECT", true, true, false, true));
1338 all.Children.Add (IEquatableLongInfo = new TypeInfo ("IEquatable<long>", "IEQUATABLE_LONG", "OBJECT", true, true, false, true));
1339 all.Children.Add (IComparableLongInfo = new TypeInfo ("IComparable<long>", "ICOMPARABLE_LONG", "OBJECT", true, true, false, true));
1341 all.Children.Add (IEquatableStringInfo = new TypeInfo ("IEquatable<string>", "IEQUATABLE_STRING", "OBJECT", true, true, false, true));
1342 all.Children.Add (IComparableStringInfo = new TypeInfo ("IComparable<string>", "ICOMPARABLE_STRING", "OBJECT", true, true, false, true));
1344 all.Children.Add (IEquatableTimeSpanInfo = new TypeInfo ("IEquatable<TimeSpan>", "IEQUATABLE_TIMESPAN", "OBJECT", true, true, false, true));
1345 all.Children.Add (IComparableTimeSpanInfo = new TypeInfo ("IComparable<TimeSpan>", "ICOMPARABLE_TIMESPAN", "OBJECT", true, true, false, true));
1347 all.Children.Add (IEquatableUintInfo = new TypeInfo ("IEquatable<uint>", "IEQUATABLE_UINT", "OBJECT", true, true, false, true));
1348 all.Children.Add (IComparableUintInfo = new TypeInfo ("IComparable<uint>", "ICOMPARABLE_UINT", "OBJECT", true, true, false, true));
1350 all.Children.Add (IEquatableUlongInfo = new TypeInfo ("IEquatable<ulong>", "IEQUATABLE_ULONG", "OBJECT", true, true, false, true));
1351 all.Children.Add (IComparableUlongInfo = new TypeInfo ("IComparable<ulong>", "ICOMPARABLE_ULONG", "OBJECT", true, true, false, true));
1353 all.Children.Add (t = new TypeInfo ("bool", "BOOL", "OBJECT", true, true, true, false));
1354 t.Interfaces.Add (IComparableInfo);
1355 t.Interfaces.Add (IComparableBoolInfo);
1356 t.Interfaces.Add (IConvertibleInfo);
1357 t.Interfaces.Add (IEquatableBoolInfo);
1359 all.Children.Add (t = new TypeInfo ("float", "FLOAT", "OBJECT", true, true, true, false));
1360 t.Interfaces.Add (IComparableInfo);
1361 t.Interfaces.Add (IComparableFloatInfo);
1362 t.Interfaces.Add (IConvertibleInfo);
1363 t.Interfaces.Add (IEquatableFloatInfo);
1364 t.Interfaces.Add (IFormattableInfo);
1366 all.Children.Add (t = new TypeInfo ("double", "DOUBLE", "OBJECT", true, true, true, false));
1367 t.Interfaces.Add (IComparableInfo);
1368 t.Interfaces.Add (IComparableDoubleInfo);
1369 t.Interfaces.Add (IConvertibleInfo);
1370 t.Interfaces.Add (IEquatableDoubleInfo);
1371 t.Interfaces.Add (IFormattableInfo);
1373 all.Children.Add (t = new TypeInfo ("guint64", "UINT64", "OBJECT", true, true, true, false));
1374 t.Interfaces.Add (IComparableInfo);
1375 t.Interfaces.Add (IComparableUlongInfo);
1376 t.Interfaces.Add (IConvertibleInfo);
1377 t.Interfaces.Add (IEquatableUlongInfo);
1378 t.Interfaces.Add (IFormattableInfo);
1380 all.Children.Add (t = new TypeInfo ("gint64", "INT64", "OBJECT", true, true, true, false));
1381 t.Interfaces.Add (IComparableInfo);
1382 t.Interfaces.Add (IComparableLongInfo);
1383 t.Interfaces.Add (IConvertibleInfo);
1384 t.Interfaces.Add (IEquatableLongInfo);
1385 t.Interfaces.Add (IFormattableInfo);
1387 all.Children.Add (t = new TypeInfo ("guint32", "UINT32", "OBJECT", true, true, true, false));
1388 t.Interfaces.Add (IComparableInfo);
1389 t.Interfaces.Add (IComparableUintInfo);
1390 t.Interfaces.Add (IConvertibleInfo);
1391 t.Interfaces.Add (IEquatableUintInfo);
1392 t.Interfaces.Add (IFormattableInfo);
1394 all.Children.Add (t = new TypeInfo ("gint32", "INT32", "OBJECT", true, true, true, false));
1395 t.Interfaces.Add (IComparableInfo);
1396 t.Interfaces.Add (IComparableIntInfo);
1397 t.Interfaces.Add (IConvertibleInfo);
1398 t.Interfaces.Add (IEquatableIntInfo);
1399 t.Interfaces.Add (IFormattableInfo);
1401 all.Children.Add (t = new TypeInfo ("char*", "STRING", "OBJECT", true, true, true, false));
1402 t.Interfaces.Add (IComparableInfo);
1403 t.Interfaces.Add (IComparableStringInfo);
1404 t.Interfaces.Add (IConvertibleInfo);
1405 t.Interfaces.Add (IEquatableStringInfo);
1406 t.Interfaces.Add (IFormattableInfo);
1408 all.Children.Add (t = new TypeInfo ("TimeSpan", "TIMESPAN", "OBJECT", true, true, true, false));
1409 t.Interfaces.Add (IComparableInfo);
1410 t.Interfaces.Add (IComparableTimeSpanInfo);
1411 t.Interfaces.Add (IEquatableTimeSpanInfo);
1413 all.Children.Add (t = new TypeInfo ("char", "CHAR", "OBJECT", true, true, true, false));
1414 t.Interfaces.Add (IComparableInfo);
1415 t.Interfaces.Add (IComparableCharInfo);
1416 t.Interfaces.Add (IConvertibleInfo);
1417 t.Interfaces.Add (IEquatableCharInfo);
1419 all.Children.Add (new TypeInfo ("NPObj", "NPOBJ", "OBJECT", true, true, true, false));
1420 all.Children.Add (new TypeInfo ("Managed", "MANAGED", "OBJECT", true, 2, true));
1422 all.Children.Add (new TypeInfo ("System.Windows.Input.Cursor", "CURSOR", "OBJECT", true, true));
1423 all.Children.Add (new TypeInfo ("System.Windows.Markup.XmlLanguage", "XMLLANGUAGE", "OBJECT", true, true));
1425 // Set IncludeInKinds for all types which inherit from EventObject
1426 foreach (MemberInfo member in all.Children.Values) {
1427 TypeInfo type = member as TypeInfo;
1428 if (type == null)
1429 continue;
1430 if (type.Name == "EventObject")
1431 type.Annotations ["IncludeInKinds"] = null;
1433 TypeReference bR = type.Base;
1434 MemberInfo m;
1435 TypeInfo b;
1436 while (bR != null) {
1437 if (bR.Value == "EventObject") {
1438 member.Annotations ["IncludeInKinds"] = null;
1441 if (!all.Children.TryGetValue (bR.Value, out m))
1442 break;
1444 b = m as TypeInfo;
1445 if (b != null)
1446 bR = b.Base;
1447 else
1448 bR = null;
1452 return all;
1455 // Returns false if there are no more tokens (reached end of code)
1456 static bool ParseClassOrStruct (Annotations annotations, MemberInfo parent, Tokenizer tokenizer)
1458 TypeInfo type = new TypeInfo ();
1460 type.Annotations = annotations;
1461 type.Header = tokenizer.CurrentFile;
1462 type.Parent = parent;
1464 type.IsPublic = tokenizer.Accept (Token2Type.Identifier, "public");
1466 if (tokenizer.Accept (Token2Type.Identifier, "class")) {
1467 type.IsClass = true;
1468 } else if (tokenizer.Accept (Token2Type.Identifier, "struct")) {
1469 type.IsStruct = true;
1470 type.IsValueType = true;
1471 } else if (tokenizer.Accept (Token2Type.Identifier, "union")) {
1472 type.IsStruct = true; // Not entirely correct, but a union can be parsed as a struct
1473 type.IsValueType = true;
1474 } else {
1475 throw new Exception (string.Format ("Expected 'class' or 'struct', not '{0}'", tokenizer.CurrentToken.value));
1478 if (tokenizer.CurrentToken.type == Token2Type.Identifier) {
1479 type.Name = tokenizer.GetIdentifier ();
1480 } else {
1481 type.Name = "<anonymous>";
1484 if (tokenizer.Accept (Token2Type.Punctuation, ";")) {
1485 // A forward declaration.
1486 //Console.WriteLine ("ParseType: Found a forward declaration to {0}", type.Name);
1487 return true;
1490 if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
1491 if (!tokenizer.Accept (Token2Type.Identifier, "public") && type.IsClass)
1492 throw new Exception (string.Format ("The base class of {0} is not public.", type.Name));
1494 type.Base = ParseTypeReference (tokenizer);
1496 // accept multiple inheritance the easy way
1497 while (tokenizer.CurrentToken.value == ",") {
1498 tokenizer.Accept (Token2Type.Punctuation, ",");
1500 while (tokenizer.CurrentToken.value != "," &&
1501 tokenizer.CurrentToken.value != "{")
1502 tokenizer.GetIdentifier ();
1505 //Console.WriteLine ("ParseType: Found {0}'s base class: {1}", type.Name, type.Base);
1508 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "{");
1510 //Console.WriteLine ("ParseType: Found a type: {0} in {1}", type.Name, type.Header);
1511 parent.Children.Add (type);
1512 ParseMembers (type, tokenizer);
1514 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "}");
1516 if (tokenizer.CurrentToken.type == Token2Type.Identifier)
1517 tokenizer.Advance (true);
1519 if (tokenizer.CurrentToken.value != ";")
1520 throw new Exception (string.Format ("Expected ';', not '{0}'", tokenizer.CurrentToken.value));
1522 return tokenizer.Advance (false);
1525 static bool ParseMembers (MemberInfo parent, Tokenizer tokenizer)
1527 Annotations properties = new Annotations ();
1528 TypeInfo parent_type = parent as TypeInfo;
1529 string accessibility;
1530 TypeReference returntype;
1531 bool is_dtor;
1532 bool is_ctor;
1533 bool is_virtual;
1534 bool is_static;
1535 bool is_const;
1536 bool is_extern;
1537 string name;
1539 //Console.WriteLine ("ParseMembers ({0})", type.Name);
1541 do {
1542 returntype = null;
1543 is_dtor = is_ctor = is_virtual = is_static = false;
1544 is_extern = is_const = false;
1545 name = null;
1546 properties = new Annotations ();
1548 if (parent_type != null)
1549 accessibility = parent_type.IsStruct ? "public" : "private";
1550 else
1551 accessibility = "public";
1553 if (tokenizer.Accept (Token2Type.Punctuation, ";"))
1554 continue;
1556 if (tokenizer.CurrentToken.value == "}")
1557 return true;
1559 while (tokenizer.CurrentToken.type == Token2Type.CommentProperty) {
1560 properties.Add (tokenizer.CurrentToken.value);
1561 tokenizer.Advance (true);
1564 //Console.WriteLine ("ParseMembers: Current token: {0}", tokenizer.CurrentToken);
1566 if (tokenizer.CurrentToken.type == Token2Type.Identifier) {
1567 string v = tokenizer.CurrentToken.value;
1568 switch (v) {
1569 case "public":
1570 case "protected":
1571 case "private":
1572 accessibility = v;
1573 tokenizer.Advance (true);
1574 tokenizer.Accept (Token2Type.Punctuation, ":");
1575 continue;
1576 case "enum":
1577 ParseEnum (properties, parent, tokenizer);
1578 continue;
1579 case "friend":
1580 while (!tokenizer.Accept (Token2Type.Punctuation, ";")) {
1581 tokenizer.Advance (true);
1583 continue;
1584 case "struct":
1585 case "class":
1586 case "union":
1587 if (!ParseClassOrStruct (properties, parent, tokenizer))
1588 return false;
1589 continue;
1590 case "typedef":
1591 StringBuilder requisite = new StringBuilder ();
1592 requisite.Append (tokenizer.CurrentToken.value);
1593 requisite.Append (' ');
1594 tokenizer.Advance (true);
1595 while (!tokenizer.Accept (Token2Type.Punctuation, ";")) {
1596 requisite.Append (tokenizer.CurrentToken.value);
1597 requisite.Append (' ');
1598 if (tokenizer.CurrentToken.value == "{") {
1599 tokenizer.Advance (true);
1600 while (!tokenizer.Accept (Token2Type.Punctuation, "}")) {
1601 requisite.Append (tokenizer.CurrentToken.value);
1602 requisite.Append (' ');
1603 tokenizer.Advance (true);
1605 requisite.Append (tokenizer.CurrentToken.value);
1606 requisite.Append (' ');
1608 tokenizer.Advance (true);
1610 requisite.Append (";");
1611 if (properties.ContainsKey ("CBindingRequisite"))
1612 cbinding_requisites.AppendLine (requisite.ToString ());
1614 continue;
1615 case "EVENTHANDLER":
1616 while (!tokenizer.Accept (Token2Type.Punctuation, ";"))
1617 tokenizer.Advance (true);
1618 continue;
1619 case "template":
1620 tokenizer.Advance (true);
1621 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "<");
1622 tokenizer.AcceptOrThrow (Token2Type.Identifier, "typename");
1623 tokenizer.GetIdentifier ();
1624 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ">");
1625 continue;
1629 do {
1630 if (tokenizer.Accept (Token2Type.Identifier, "virtual")) {
1631 is_virtual = true;
1632 continue;
1635 if (tokenizer.Accept (Token2Type.Identifier, "static")) {
1636 is_static = true;
1637 continue;
1640 if (tokenizer.Accept (Token2Type.Identifier, "const")) {
1641 is_const = true;
1642 continue;
1645 if (tokenizer.Accept (Token2Type.Identifier, "extern")) {
1646 is_extern = true;
1647 continue;
1650 if (tokenizer.Accept (Token2Type.Identifier, "volatile")) {
1651 continue;
1654 if (tokenizer.Accept (Token2Type.Identifier, "G_GNUC_INTERNAL")) {
1655 continue;
1658 break;
1659 } while (true);
1661 if (is_extern && tokenizer.Accept (Token2Type.Literal, "C")) {
1662 tokenizer.SyncWithEndBrace ();
1663 continue;
1666 if (tokenizer.Accept (Token2Type.Punctuation, "~")) {
1667 is_dtor = true;
1668 if (!is_virtual) {
1669 TypeInfo ti = parent as TypeInfo;
1670 if (ti != null && ti.Base != null)
1671 Console.WriteLine ("The class {0} has a non-virtual destructor, and it's base class is {2} ({1}).", parent.Name, parent.Header, ti != null && ti.Base != null ? ti.Base.Value : "<none>");
1675 if (is_dtor) {
1676 name = "~" + tokenizer.GetIdentifier ();
1677 returntype = new TypeReference ("void");
1678 } else {
1679 returntype = ParseTypeReference (tokenizer);
1681 if (tokenizer.CurrentToken.value == "<") {
1682 tokenizer.Advance (true);
1683 while (!tokenizer.Accept (Token2Type.Punctuation, ">"))
1684 tokenizer.Advance (true);
1687 if (returntype.Value == parent.Name && tokenizer.CurrentToken.value == "(") {
1688 is_ctor = true;
1689 name = returntype.Value;
1690 returntype.Value += "*";
1691 } else {
1692 name = tokenizer.GetIdentifier ();
1695 returntype.IsConst = is_const;
1696 returntype.IsReturnType = true;
1698 //Console.WriteLine ("ParseMembers: found member '{0}' is_ctor: {1}", name, is_ctor);
1700 if (tokenizer.Accept (Token2Type.Punctuation, "(")) {
1701 // Method
1702 MethodInfo method = new MethodInfo ();
1703 method.Header = tokenizer.CurrentFile;
1704 method.Parent = parent;
1705 method.Annotations = properties;
1706 method.Name = name;
1707 method.IsConstructor = is_ctor;
1708 method.IsDestructor = is_dtor;
1709 method.IsVirtual = is_virtual;
1710 method.IsStatic = is_static;
1711 method.IsPublic = accessibility == "public";
1712 method.IsPrivate = accessibility == "private";
1713 method.IsProtected = accessibility == "protected";
1714 method.ReturnType = returntype;
1716 //Console.WriteLine ("ParseMembers: found method '{0}' is_ctor: {1}", name, is_ctor);
1718 if (!tokenizer.Accept (Token2Type.Punctuation, ")")) {
1719 string param_value = null;
1720 do {
1721 ParameterInfo parameter = new ParameterInfo (method);
1723 while (tokenizer.CurrentToken.type == Token2Type.CommentProperty) {
1724 parameter.Annotations.Add (tokenizer.CurrentToken.value);
1725 tokenizer.Advance (true);
1728 if (tokenizer.Accept (Token2Type.Punctuation, ".") && tokenizer.Accept (Token2Type.Punctuation, ".") && tokenizer.Accept (Token2Type.Punctuation, ".")) {
1729 // ... variable argument declaration
1730 parameter.ParameterType = new TypeReference ("...");
1731 } else {
1732 parameter.ParameterType = ParseTypeReference (tokenizer);
1734 if (tokenizer.CurrentToken.value != "," && tokenizer.CurrentToken.value != ")") {
1735 parameter.Name = tokenizer.GetIdentifier ();
1736 if (tokenizer.Accept (Token2Type.Punctuation, "[")) {
1737 if (tokenizer.CurrentToken.type == Token2Type.Identifier)
1738 tokenizer.Advance (true);
1739 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "]");
1741 if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
1742 param_value = string.Empty;
1743 if (tokenizer.Accept (Token2Type.Punctuation, "-"))
1744 param_value = "-";
1745 param_value += tokenizer.GetIdentifier ();
1746 if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
1747 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ":");
1748 param_value += "::" + tokenizer.GetIdentifier ();
1752 method.Parameters.Add (parameter);
1753 //Console.WriteLine ("ParseMember: got parameter, type: '{0}' name: '{1}' value: '{2}'", parameter.ParameterType.Value, parameter.Name, param_value);
1754 } while (tokenizer.Accept (Token2Type.Punctuation, ","));
1755 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ")");
1758 parent.Children.Add (method);
1760 //Allow const member functions, ignore the const keyword
1761 tokenizer.Accept (Token2Type.Identifier, "const");
1763 if (tokenizer.CurrentToken.value == "{") {
1764 //Console.WriteLine ("ParseMember: member has body, skipping it");
1765 tokenizer.SyncWithEndBrace ();
1766 } else if (is_ctor && tokenizer.Accept (Token2Type.Punctuation, ":")) {
1767 // ctor method implemented in header with field initializers and/or base class ctor call
1768 tokenizer.FindStartBrace ();
1769 tokenizer.SyncWithEndBrace ();
1770 //Console.WriteLine ("ParseMember: skipped ctor method implementation");
1771 } else if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
1772 // pure virtual method
1773 tokenizer.AcceptOrThrow (Token2Type.Identifier, "0");
1774 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ";");
1775 method.IsAbstract = true;
1776 } else {
1777 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ";");
1779 } else {
1780 if (is_ctor || is_dtor)
1781 throw new Exception (string.Format ("Expected '(', not '{0}'", tokenizer.CurrentToken.value));
1783 if (name == "operator") {
1784 while (true) {
1785 if (tokenizer.CurrentToken.value == ";") {
1786 // End of operator
1787 break;
1788 } else if (tokenizer.CurrentToken.value == "{") {
1789 // In-line implementation
1790 tokenizer.SyncWithEndBrace ();
1791 break;
1793 tokenizer.Advance (true);
1795 //Console.WriteLine ("ParseMembers: skipped operator");
1796 } else {
1797 FieldInfo field = new FieldInfo ();
1798 field.IsConst = is_const;
1799 field.IsStatic = is_static;
1800 field.IsExtern = is_extern;
1801 field.Name = name;
1802 field.FieldType = returntype;
1803 field.IsPublic = accessibility == "public";
1804 field.IsPrivate = accessibility == "private";
1805 field.IsProtected = accessibility == "protected";
1806 field.Annotations = properties;
1808 // Field
1809 do {
1810 //Console.WriteLine ("ParseMembers: found field '{0}'", name);
1811 field.Parent = parent;
1812 parent.Children.Add (field);
1814 if (tokenizer.Accept (Token2Type.Punctuation, "[")) {
1815 while (!tokenizer.Accept (Token2Type.Punctuation, "]")) {
1816 tokenizer.Advance (true);
1819 if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
1820 field.BitField = tokenizer.GetIdentifier ();
1822 if (tokenizer.Accept (Token2Type.Punctuation, ",")) {
1823 field = new FieldInfo ();
1824 if (tokenizer.Accept (Token2Type.Punctuation, "*")) {
1825 // ok
1827 field.Name = tokenizer.GetIdentifier ();
1828 field.FieldType = returntype;
1829 continue;
1831 if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
1832 tokenizer.Advance (true); /* this can be an arbitrary long expression, sync with the ';'? */
1834 break;
1835 } while (true);
1837 tokenizer.Accept (Token2Type.Punctuation, ";");
1840 } while (true);
1843 static void ParseEnum (Annotations properties, MemberInfo parent, Tokenizer tokenizer)
1845 FieldInfo field;
1846 StringBuilder value = new StringBuilder ();
1847 TypeInfo type = new TypeInfo ();
1849 type.Annotations = properties;
1850 type.IsEnum = true;
1852 tokenizer.AcceptOrThrow (Token2Type.Identifier, "enum");
1853 if (tokenizer.CurrentToken.type == Token2Type.Identifier) {
1854 type.Name = tokenizer.GetIdentifier ();
1855 } else {
1856 type.Name = "<anonymous>";
1858 parent.Children.Add (type);
1860 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "{");
1862 //Console.WriteLine ("ParseEnum: {0}", name);
1864 while (tokenizer.CurrentToken.type == Token2Type.Identifier) {
1865 field = new FieldInfo ();
1866 field.Name = tokenizer.GetIdentifier ();
1867 value.Length = 0;
1868 if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
1869 while (tokenizer.CurrentToken.value != "," && tokenizer.CurrentToken.value != "}") {
1870 value.Append (" ");
1871 value.Append (tokenizer.CurrentToken.value);
1872 tokenizer.Advance (true);
1875 field.Value = value.ToString ();
1876 type.Children.Add (field);
1877 //Console.WriteLine ("ParseEnum: {0}: {1} {2} {3}", name, field, value.Length != 0 != null ? "=" : "", value);
1879 if (!tokenizer.Accept (Token2Type.Punctuation, ","))
1880 break;
1883 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "}");
1884 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ";");
1887 public static TypeReference ParseTypeReference (Tokenizer tokenizer)
1889 TypeReference tr = new TypeReference ();
1890 StringBuilder result = new StringBuilder ();
1892 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1893 tr.IsConst = true;
1895 if (tokenizer.Accept (Token2Type.Identifier, "unsigned"))
1896 result.Append ("unsigned");
1898 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1899 tr.IsConst = true;
1901 result.Append (tokenizer.GetIdentifier ());
1903 if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
1904 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ":");
1905 result.Append ("::");
1906 result.Append (tokenizer.GetIdentifier ());
1909 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1910 tr.IsConst = true;
1912 while (tokenizer.Accept (Token2Type.Punctuation, "*"))
1913 result.Append ("*");
1915 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1916 tr.IsConst = true;
1918 if (tokenizer.Accept (Token2Type.Punctuation, "&"))
1919 result.Append ("&");
1921 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1922 tr.IsConst = true;
1924 //Console.WriteLine ("ParseTypeReference: parsed '{0}'", result.ToString ());
1926 tr.Value = result.ToString ();
1928 return tr;
1931 public static string getU (string v)
1933 if (v.Contains ("::"))
1934 v = v.Substring (v.IndexOf ("::") + 2);
1936 v = v.ToUpper ();
1937 v = v.Replace ("DEPENDENCYOBJECT", "DEPENDENCY_OBJECT");
1938 if (v.Length > "COLLECTION".Length && !v.StartsWith ("COLLECTION"))
1939 v = v.Replace ("COLLECTION", "_COLLECTION");
1940 if (v.Length > "DICTIONARY".Length)
1941 v = v.Replace ("DICTIONARY", "_DICTIONARY");
1942 return v;
1945 public void GenerateTypes_G (GlobalInfo all)
1947 string base_dir = Environment.CurrentDirectory;
1948 string class_dir = Path.Combine (base_dir, "class");
1949 string moon_moonlight_dir = Path.Combine (class_dir, "System.Windows");
1950 List<TypeInfo> types = new List<TypeInfo> (all.GetDependencyObjects ());
1952 StringBuilder text = new StringBuilder ();
1954 Helper.WriteWarningGenerated (text);
1956 text.AppendLine ("using Mono;");
1957 text.AppendLine ("using System;");
1958 text.AppendLine ("using System.Reflection;");
1959 text.AppendLine ("using System.Collections.Generic;");
1960 text.AppendLine ("");
1961 text.AppendLine ("namespace Mono {");
1962 text.AppendLine ("\tpartial class Types {");
1963 text.AppendLine ("\t\tprivate void CreateNativeTypes ()");
1964 text.AppendLine ("\t\t{");
1965 text.AppendLine ("\t\t\tType t;");
1966 text.AppendLine ("\t\t\ttry {");
1968 foreach (MemberInfo m in all.Children.Values) {
1969 TypeInfo t = m as TypeInfo;
1970 if (t == null)
1971 continue;
1972 if (types.Contains (t))
1973 continue;
1974 types.Add (t);
1977 types.Sort (new Members.MembersSortedByManagedFullName <TypeInfo> ());
1979 for (int i = 0; i < types.Count; i++) {
1980 TypeInfo t = types [i];
1981 string type = t.ManagedName;
1983 if (String.IsNullOrEmpty (t.Namespace) || t.Namespace == "None" || t.Name.StartsWith ("MoonWindow"))
1984 continue;
1986 if (type == "PresentationFrameworkCollection`1")
1987 type = "PresentationFrameworkCollection<>";
1989 //Log.WriteLine ("Found Kind.{0} in {1} which result in type: {2}.{3}", kind, file, ns, type);
1991 text.Append ("\t\t\t\tt = typeof (");
1992 text.Append (t.Namespace);
1993 text.Append (".");
1994 text.Append (type);
1995 text.AppendLine ("); ");
1997 text.Append ("\t\t\t\ttypes.Add (t, new ManagedType (t, Kind.");
1998 text.Append (t.KindName);
1999 text.AppendLine ("));");
2002 // now handle the primitive types
2003 output_native_type_delegate f = delegate (string t, string k) {
2004 text.Append ("\t\t\t\tt = typeof (");
2005 text.Append (t);
2006 text.AppendLine (");");
2009 text.Append ("\t\t\t\ttypes.Add (t, new ManagedType (t, Kind.");
2010 text.Append (k);
2011 text.AppendLine ("));");
2014 f ("char", "UINT32");
2015 f ("object", "OBJECT");
2016 f ("bool", "BOOL");
2017 f ("double", "DOUBLE");
2018 f ("float", "FLOAT");
2019 f ("ulong", "UINT64");
2020 f ("long", "INT64");
2021 f ("uint", "UINT32");
2022 f ("int", "INT32");
2023 f ("string", "STRING");
2024 f ("TimeSpan", "TIMESPAN");
2026 // all the interfaces
2027 f ("IComparable", "ICOMPARABLE");
2028 f ("IFormattable", "IFORMATTABLE");
2029 f ("IConvertible", "ICONVERTIBLE");
2030 f ("IEquatable<bool>", "IEQUATABLE_BOOL");
2031 f ("IComparable<bool>", "ICOMPARABLE_BOOL");
2032 f ("IEquatable<double>", "IEQUATABLE_DOUBLE");
2033 f ("IComparable<double>", "ICOMPARABLE_DOUBLE");
2034 f ("IEquatable<float>", "IEQUATABLE_FLOAT");
2035 f ("IComparable<float>", "ICOMPARABLE_FLOAT");
2036 f ("IEquatable<char>", "IEQUATABLE_CHAR");
2037 f ("IComparable<char>", "ICOMPARABLE_CHAR");
2038 f ("IEquatable<int>", "IEQUATABLE_INT");
2039 f ("IComparable<int>", "ICOMPARABLE_INT");
2040 f ("IEquatable<long>", "IEQUATABLE_LONG");
2041 f ("IComparable<long>", "ICOMPARABLE_LONG");
2042 f ("IEquatable<string>", "IEQUATABLE_STRING");
2043 f ("IComparable<string>", "ICOMPARABLE_STRING");
2044 f ("IEquatable<TimeSpan>", "IEQUATABLE_TIMESPAN");
2045 f ("IComparable<TimeSpan>", "ICOMPARABLE_TIMESPAN");
2046 f ("IEquatable<uint>", "IEQUATABLE_UINT");
2047 f ("IComparable<uint>", "ICOMPARABLE_UINT");
2048 f ("IEquatable<ulong>", "IEQUATABLE_ULONG");
2049 f ("IComparable<ulong>", "ICOMPARABLE_ULONG");
2051 f ("System.Windows.Application", "APPLICATION");
2052 f ("System.Windows.Thickness", "THICKNESS");
2053 f ("System.Windows.CornerRadius", "CORNERRADIUS");
2054 f ("System.Windows.PropertyPath", "PROPERTYPATH");
2055 f ("System.Windows.Point", "POINT");
2056 f ("System.Windows.Rect", "RECT");
2057 f ("System.Windows.Size", "SIZE");
2058 f ("System.Windows.FontStretch", "FONTSTRETCH");
2059 f ("System.Windows.FontWeight", "FONTWEIGHT");
2060 f ("System.Windows.FontStyle", "FONTSTYLE");
2061 f ("System.Windows.Input.Cursor", "CURSOR");
2062 f ("System.Windows.Media.FontFamily", "FONTFAMILY");
2063 f ("System.Windows.Markup.XmlLanguage", "XMLLANGUAGE");
2065 text.AppendLine ("\t\t\t} catch (Exception ex) {");
2066 text.AppendLine ("\t\t\t\tConsole.WriteLine (\"There was an error while loading native types: \" + ex.ToString ());");
2067 text.AppendLine ("\t\t\t}");
2068 text.AppendLine ("\t\t}");
2069 text.AppendLine ("\t}");
2070 text.AppendLine ("}");
2072 Log.WriteLine ("typeandkidngen done");
2074 Helper.WriteAllText (Path.Combine (Path.Combine (moon_moonlight_dir, "Mono"), "Types.g.cs"), text.ToString ());
2077 private static void GenerateCBindings (GlobalInfo info, string dir)
2079 List<MethodInfo> methods;
2080 StringBuilder header = new StringBuilder ();
2081 StringBuilder impl = new StringBuilder ();
2082 List <string> headers = new List<string> ();
2083 List <string> classes = new List<string> ();
2084 List <string> structs = new List<string> ();
2086 string last_type = string.Empty;
2088 methods = info.CPPMethodsToBind;
2090 Helper.WriteWarningGenerated (header);;
2091 Helper.WriteWarningGenerated (impl);
2093 header.AppendLine ("#ifndef __MOONLIGHT_C_BINDING_H__");
2094 header.AppendLine ("#define __MOONLIGHT_C_BINDING_H__");
2095 header.AppendLine ();
2096 header.AppendLine ("#include <glib.h>");
2097 header.AppendLine ("#include <cairo.h>");
2098 header.AppendLine ();
2099 header.AppendLine ("#include \"enums.h\"");
2100 header.AppendLine ();
2101 foreach (MemberInfo member in info.Children.Values) {
2102 TypeInfo type = member as TypeInfo;
2103 if (type == null)
2104 continue;
2106 if (type.IsClass) {
2107 if (!classes.Contains (type.Name))
2108 classes.Add (type.Name);
2109 } else if (type.IsStruct) {
2110 if (!structs.Contains (type.Name))
2111 structs.Add (type.Name);
2115 foreach (MemberInfo method in methods) {
2116 string h;
2118 if (method.ParentType != null) {
2119 TypeInfo type = method.ParentType;
2120 if (type.IsClass) {
2121 if (!classes.Contains (type.Name))
2122 classes.Add (type.Name);
2123 } else if (type.IsStruct) {
2124 if (!structs.Contains (type.Name))
2125 structs.Add (type.Name);
2129 if (string.IsNullOrEmpty (method.Header))
2130 continue;
2131 if (!method.Header.StartsWith (dir))
2132 continue;
2134 h = Path.GetFileName (method.Header);
2136 if (!headers.Contains (h))
2137 headers.Add (h);
2139 header.AppendLine (forward_decls.ToString ());
2140 classes.Sort ();
2141 structs.Sort ();
2142 foreach (string c in classes) {
2143 header.Append ("class ");
2144 header.Append (c);
2145 header.AppendLine (";");
2147 header.AppendLine ();
2148 foreach (string s in structs) {
2149 header.Append ("struct ");
2150 header.Append (s);
2151 header.AppendLine (";");
2153 header.AppendLine ();
2154 header.AppendLine (cbinding_requisites.ToString ());
2156 header.AppendLine ();
2157 header.AppendLine ("G_BEGIN_DECLS");
2158 header.AppendLine ();
2160 impl.AppendLine ("#include <config.h>");
2161 impl.AppendLine ();
2162 impl.AppendLine ("#include <stdio.h>");
2163 impl.AppendLine ("#include <stdlib.h>");
2164 impl.AppendLine ();
2165 impl.AppendLine ("#include \"cbinding.h\"");
2166 impl.AppendLine ();
2167 headers.Sort ();
2168 foreach (string h in headers) {
2169 impl.Append ("#include \"");
2170 impl.Append (h);
2171 impl.AppendLine ("\"");
2174 foreach (MemberInfo member in methods) {
2175 MethodInfo method = (MethodInfo) member;
2177 if (!method.Header.StartsWith (dir))
2178 continue;
2180 if (last_type != method.Parent.Name) {
2181 last_type = method.Parent.Name;
2182 foreach (StringBuilder text in new StringBuilder [] {header, impl}) {
2183 text.AppendLine ("/**");
2184 text.Append (" * ");
2185 text.AppendLine (last_type);
2186 text.AppendLine (" **/");
2190 WriteHeaderMethod (method.CMethod, method, header, info);
2191 header.AppendLine ();
2193 WriteImplMethod (method.CMethod, method, impl, info);
2194 impl.AppendLine ();
2195 impl.AppendLine ();
2198 header.AppendLine ();
2199 header.AppendLine ("G_END_DECLS");
2200 header.AppendLine ();
2201 header.AppendLine ("#endif");
2203 Helper.WriteAllText (Path.Combine (dir, "cbinding.h"), header.ToString ());
2204 Helper.WriteAllText (Path.Combine (dir, "cbinding.cpp"), impl.ToString ());
2207 public static void GenerateCBindings (GlobalInfo info)
2209 string base_dir = Environment.CurrentDirectory;
2210 string plugin_dir = Path.Combine (base_dir, "plugin");
2211 string moon_dir = Path.Combine (base_dir, "src");
2213 GenerateCBindings (info, moon_dir);
2214 GenerateCBindings (info, plugin_dir);
2217 static void WriteHeaderMethod (MethodInfo cmethod, MethodInfo cppmethod, StringBuilder text, GlobalInfo info)
2219 Log.WriteLine ("Writing header: {0}::{1} (Version: '{2}', GenerateManaged: {3})",
2220 cmethod.Parent.Name, cmethod.Name,
2221 cmethod.Annotations.GetValue ("Version"),
2222 cmethod.Annotations.ContainsKey ("GenerateManaged"));
2224 if (cmethod.Annotations.ContainsKey ("GeneratePInvoke"))
2225 text.AppendLine ("/* @GeneratePInvoke */");
2226 cmethod.ReturnType.Write (text, SignatureType.NativeC, info);
2227 if (!cmethod.ReturnType.IsPointer)
2228 text.Append (" ");
2229 text.Append (cmethod.Name);
2230 cmethod.Parameters.Write (text, SignatureType.NativeC, false);
2231 text.AppendLine (";");
2234 static void WriteImplMethod (MethodInfo cmethod, MethodInfo cppmethod, StringBuilder text, GlobalInfo info)
2236 bool is_void = cmethod.ReturnType.Value == "void";
2237 bool is_ctor = cmethod.IsConstructor;
2238 bool is_static = cmethod.IsStatic;
2239 bool is_dtor = cmethod.IsDestructor;
2240 bool check_instance = !is_static && !is_ctor;
2241 bool check_error = false;
2243 foreach (ParameterInfo parameter in cmethod.Parameters) {
2244 if (parameter.ParameterType.Value == "MoonError*") {
2245 check_error = true;
2246 break;
2250 cmethod.ReturnType.Write (text, SignatureType.NativeC, info);
2251 text.AppendLine ();
2252 text.Append (cmethod.Name);
2253 cmethod.Parameters.Write (text, SignatureType.NativeC, false);
2254 text.AppendLine ("");
2255 text.AppendLine ("{");
2257 if (is_ctor) {
2258 text.Append ("\treturn new ");
2259 text.Append (cmethod.Parent.Name);
2260 cmethod.Parameters.Write (text, SignatureType.NativeC, true);
2261 text.AppendLine (";");
2262 } else if (is_dtor) {
2263 text.AppendLine ("\tdelete instance;");
2264 } else {
2265 if (check_instance) {
2266 text.AppendLine ("\tif (instance == NULL)");
2268 if (cmethod.ReturnType.Value == "void") {
2269 text.Append ("\t\treturn");
2270 } else if (cmethod.ReturnType.Value.Contains ("*")) {
2271 text.Append ("\t\treturn NULL");
2272 } else if (cmethod.ReturnType.Value == "Type::Kind") {
2273 text.Append ("\t\treturn Type::INVALID");
2274 } else if (cmethod.ReturnType.Value == "bool") {
2275 text.Append ("\t\treturn false");
2276 } else if (cmethod.ReturnType.Value == "Point") {
2277 text.Append ("\t\treturn Point (0, 0)");
2278 } else {
2279 text.AppendLine ("\t\t// Need to find a proper way to get the default value for the specified type and return that if instance is NULL.");
2280 text.Append ("\t\treturn");
2281 text.Append (" (");
2282 text.Append (cmethod.ReturnType.Value);
2283 text.Append (") 0");
2285 text.AppendLine (";");
2287 text.AppendLine ("\t");
2290 if (check_error) {
2291 text.AppendLine ("\tif (error == NULL)");
2292 text.Append ("\t\tg_warning (\"Moonlight: Called ");
2293 text.Append (cmethod.Name);
2294 text.AppendLine (" () with error == NULL.\");");
2297 text.Append ("\t");
2298 if (!is_void)
2299 text.Append ("return ");
2301 if (is_static) {
2302 text.Append (cmethod.Parent.Name);
2303 text.Append ("::");
2304 } else {
2305 text.Append ("instance->");
2306 cmethod.Parameters [0].DisableWriteOnce = true;
2308 text.Append (cppmethod.Name);
2309 cmethod.Parameters.Write (text, SignatureType.NativeC, true);
2310 text.AppendLine (";");
2313 text.AppendLine ("}");
2316 static void GenerateTypeStaticCpp (GlobalInfo all)
2318 string header;
2319 List<string> headers = new List<string> ();
2321 StringBuilder text = new StringBuilder ();
2323 Helper.WriteWarningGenerated (text);
2325 text.AppendLine ("#include <config.h>");
2326 text.AppendLine ();
2327 text.AppendLine ("#include <stdlib.h>");
2329 headers.Add ("cbinding.h");
2330 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
2331 if (t.C_Constructor == string.Empty || t.C_Constructor == null || !t.GenerateCBindingCtor) {
2332 //Console.WriteLine ("{0} does not have a C ctor", t.FullName);
2333 if (t.GetTotalEventCount () == 0)
2334 continue;
2337 if (string.IsNullOrEmpty (t.Header)) {
2338 // Console.WriteLine ("{0} does not have a header", t.FullName);
2339 continue;
2342 //Console.WriteLine ("{0}'s header is {1}", t.FullName, t.Header);
2344 header = Path.GetFileName (t.Header);
2345 if (!headers.Contains (header))
2346 headers.Add (header);
2349 // Loop through all the classes and check which headers
2350 // are needed for the c constructors
2351 text.AppendLine ("");
2352 headers.Sort ();
2353 foreach (string h in headers) {
2354 text.Append ("#include \"");
2355 text.Append (h);
2356 text.AppendLine ("\"");
2358 text.AppendLine ();
2360 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
2361 if (t.GetEventCount () == 0)
2362 continue;
2365 foreach (FieldInfo field in t.Events) {
2366 text.Append ("const int ");
2367 text.Append (t.Name);
2368 text.Append ("::");
2369 text.Append (field.EventName);
2370 text.Append ("Event = ");
2371 text.Append (t.GetEventId (field));
2372 text.AppendLine (";");
2376 // Create the arrays of event names for the classes which have events
2377 text.AppendLine ("");
2378 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
2380 if (t.Events.Count > 0) {
2381 text.Append ("const char *");
2382 text.Append (t.KindName);
2383 text.Append ("_Events [] = { ");
2385 foreach (FieldInfo field in t.Events) {
2386 text.Append ("\"");
2387 text.Append (field.EventName);
2388 text.Append ("\", ");
2391 text.AppendLine ("NULL };");
2394 if (t.Interfaces.Count > 0) {
2395 text.Append ("const Type::Kind ");
2396 text.Append (t.KindName);
2397 text.Append ("_Interfaces[] = { ");
2399 for (int i = 0; i < t.Interfaces.Count; i ++) {
2400 text.Append ("Type::");
2401 text.Append (t.Interfaces[i].KindName);
2402 if (i < t.Interfaces.Count - 1)
2403 text.Append (", ");
2406 text.AppendLine (" };");
2410 // Create the array of type data
2411 text.AppendLine ("");
2412 text.AppendLine ("void");
2413 text.AppendLine ("Types::RegisterNativeTypes ()");
2414 text.AppendLine ("{");
2415 text.AppendLine ("\ttypes [(int) Type::INVALID] = new Type (Type::INVALID, Type::INVALID, false, false, NULL, 0, 0, NULL, 0, NULL, false, NULL, NULL );");
2416 foreach (TypeInfo type in all.Children.SortedTypesByKind) {
2417 MemberInfo member;
2418 TypeInfo parent = null;
2419 string events = "NULL";
2420 string interfaces = "NULL";
2422 if (!type.Annotations.ContainsKey ("IncludeInKinds"))
2423 continue;
2425 if (type.Base != null && type.Base.Value != null && all.Children.TryGetValue (type.Base.Value, out member))
2426 parent = (TypeInfo) member;
2428 if (type.Events != null && type.Events.Count != 0)
2429 events = type.KindName + "_Events";
2431 if (type.Interfaces.Count != 0)
2432 interfaces = type.KindName + "_Interfaces";
2434 text.AppendLine (string.Format (@" types [(int) {0}] = new Type ({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12});",
2435 "Type::" + type.KindName,
2436 type.KindName == "OBJECT" ? "Type::INVALID" : ("Type::" + (parent != null ? parent.KindName : "OBJECT")),
2437 type.IsValueType ? "true" : "false",
2438 type.IsInterface ? "true" : "false",
2439 "\"" + type.Name + "\"",
2440 type.GetEventCount (),
2441 type.GetTotalEventCount (),
2442 events,
2443 type.Interfaces.Count,
2444 interfaces,
2445 type.DefaultCtorVisible ? "true" : "false",
2446 (type.C_Constructor != null && type.GenerateCBindingCtor) ? string.Concat ("(create_inst_func *) ", type.C_Constructor) : "NULL",
2447 type.ContentProperty != null ? string.Concat ("\"", type.ContentProperty, "\"") : "NULL"
2452 text.AppendLine ("\ttypes [(int) Type::LASTTYPE] = new Type (Type::LASTTYPE, Type::INVALID, false, false, NULL, 0, 0, NULL, 0, NULL, false, NULL, NULL);");
2454 text.AppendLine ("}");
2456 text.AppendLine ();
2458 Helper.WriteAllText ("src/type-generated.cpp", text.ToString ());
2461 static void GenerateTypeH (GlobalInfo all)
2463 const string file = "src/type.h";
2464 StringBuilder text;
2465 string contents = File.ReadAllText (file + ".in");
2467 contents = contents.Replace ("/*DO_KINDS*/", all.Children.GetKindsForEnum ().ToString ());
2469 text = new StringBuilder ();
2471 Helper.WriteWarningGenerated (text);
2473 contents = text.ToString () + contents;
2475 Helper.WriteAllText (file, contents);
2478 static void GenerateKindCs ()
2480 const string file = "src/type.h";
2481 StringBuilder text = new StringBuilder ();
2482 string contents = File.ReadAllText (file);
2483 int a = contents.IndexOf ("// START_MANAGED_MAPPING") + "// START_MANAGED_MAPPING".Length;
2484 int b = contents.IndexOf ("// END_MANAGED_MAPPING");
2485 string values = contents.Substring (a, b - a);
2487 Helper.WriteWarningGenerated (text);
2489 text.AppendLine ("namespace Mono {");
2490 text.AppendLine ("#if NET_2_1");
2491 text.AppendLine ("\tinternal enum Kind {");
2492 text.AppendLine ("#else");
2493 text.AppendLine ("\tpublic enum Kind {");
2494 text.AppendLine ("#endif");
2495 text.AppendLine (values);
2496 text.AppendLine ("\t}");
2497 text.AppendLine ("}");
2499 string realfile = "class/System.Windows/Mono/Kind.cs".Replace ('/', Path.DirectorySeparatorChar);
2500 Helper.WriteAllText (realfile, text.ToString ());
2503 static void GenerateValueH (GlobalInfo all)
2505 const string file = "src/value.h";
2506 StringBuilder result = new StringBuilder ();
2508 Helper.WriteWarningGenerated (result);
2510 using (StreamReader reader = new StreamReader (file + ".in")) {
2511 string line;
2512 line = reader.ReadLine ();
2513 while (line != null) {
2514 if (line.Contains ("/*DO_FWD_DECLS*/")) {
2515 foreach (TypeInfo type in all.Children.SortedTypesByKind) {
2516 if (!type.Annotations.ContainsKey("IncludeInKinds") ||
2517 type.Annotations.ContainsKey("SkipValue") ||
2518 type.IsNested ||
2519 type.IsStruct)
2520 continue;
2522 if (type.IsStruct) {
2523 forward_decls.Append ("struct ");
2524 } else {
2525 forward_decls.Append ("class ");
2527 forward_decls.Append (type.Name);
2528 forward_decls.AppendLine (";");
2530 forward_decls.AppendLine ();
2531 result.Append (forward_decls.ToString ());
2532 } else if (line.Contains ("/*DO_AS*/")) {
2533 foreach (TypeInfo type in all.Children.SortedTypesByKind) {
2534 if (!type.Annotations.ContainsKey("IncludeInKinds") ||
2535 type.Annotations.ContainsKey("SkipValue") ||
2536 type.IsNested ||
2537 type.IsStruct)
2538 continue;
2540 //do_as.AppendLine (string.Format (" {1,-30} As{0} () {{ checked_get_subclass (Type::{2}, {0}) }}", type.Name, type.Name + "*", type.KindName));
2542 result.Append ('\t');
2543 result.Append (type.Name);
2544 result.Append ("*");
2545 result.Append (' ', 40 - type.Name.Length);
2546 result.Append ("As");
2547 result.Append (type.Name);
2548 result.Append (" (Types *types = NULL) { checked_get_subclass (Type::");
2549 result.Append (type.KindName);
2550 result.Append (", ");
2551 result.Append (type.Name);
2552 result.Append (") }");
2553 result.AppendLine ();
2555 result.AppendLine ();
2556 } else {
2557 result.AppendLine (line);
2559 line = reader.ReadLine ();
2563 Helper.WriteAllText (file, result.ToString ());
2566 #if false
2567 static bool IsManuallyDefined (string NativeMethods_cs, string method)
2569 if (NativeMethods_cs.Contains (" " + method + " "))
2570 return true;
2571 else if (NativeMethods_cs.Contains (" " + method + "("))
2572 return true;
2573 else if (NativeMethods_cs.Contains ("\"" + method + "\""))
2574 return true;
2575 else
2576 return false;
2578 #endif
2580 static void GeneratePInvokes (GlobalInfo all)
2582 string base_dir = Environment.CurrentDirectory;
2583 List <MethodInfo> methods = new List<MethodInfo> ();
2584 StringBuilder text = new StringBuilder ();
2585 string NativeMethods_cs;
2587 NativeMethods_cs = File.ReadAllText (Path.Combine (base_dir, "class/System.Windows/Mono/NativeMethods.cs".Replace ('/', Path.DirectorySeparatorChar)));
2589 methods = all.CPPMethodsToBind;
2591 foreach (MemberInfo info in all.Children.Values) {
2592 MethodInfo minfo = info as MethodInfo;
2593 if (minfo == null)
2594 continue;
2595 if (!minfo.Annotations.ContainsKey ("GeneratePInvoke"))
2596 continue;
2597 foreach (MethodInfo mi in methods) {
2598 if (mi.CMethod.Name == minfo.Name) {
2599 minfo = null;
2600 break;
2603 if (minfo == null)
2604 continue;
2605 //Console.WriteLine ("Added: {0} IsSrc: {1} IsPlugin: {2} Header: {3}", minfo.Name, minfo.IsSrcMember, minfo.IsPluginMember, minfo.Header);
2606 methods.Add (minfo);
2609 Helper.WriteWarningGenerated (text);
2610 text.AppendLine ("using System;");
2611 text.AppendLine ("using System.Windows;");
2612 text.AppendLine ("using System.Runtime.InteropServices;");
2613 text.AppendLine ("");
2614 text.AppendLine ("namespace Mono {");
2615 text.AppendLine ("\tinternal static partial class NativeMethods");
2616 text.AppendLine ("\t{");
2617 text.AppendLine ("\t\t/* moonplugin methods */");
2618 text.AppendLine ("\t");
2619 foreach (MethodInfo method in methods) {
2620 if (!method.IsPluginMember || !method.Annotations.ContainsKey ("GeneratePInvoke"))
2621 continue;
2622 WritePInvokeMethod (NativeMethods_cs, method, text, "moonplugin");
2623 text.AppendLine ();
2626 text.AppendLine ("\t");
2627 text.AppendLine ("\t\t/* libmoon methods */");
2628 text.AppendLine ("\t");
2629 foreach (MethodInfo method in methods) {
2630 if (!method.IsSrcMember || !method.Annotations.ContainsKey ("GeneratePInvoke"))
2631 continue;
2632 WritePInvokeMethod (NativeMethods_cs, method, text, "moon");
2633 text.AppendLine ();
2635 text.AppendLine ("\t}");
2636 text.AppendLine ("}");
2638 Helper.WriteAllText (Path.Combine (base_dir, "class/System.Windows/Mono/GeneratedPInvokes.cs".Replace ('/', Path.DirectorySeparatorChar)), text.ToString ());
2641 static void WritePInvokeMethod (string NativeMethods_cs, MethodInfo method, StringBuilder text, string library)
2643 bool marshal_string_returntype = false;
2644 bool marshal_moonerror = false;
2645 bool generate_wrapper = false;
2646 // bool is_manually_defined;
2647 bool comment_out;
2648 bool is_void = false;
2649 bool contains_unknown_types;
2650 string name;
2651 string managed_name;
2652 string tabs;
2653 TypeReference returntype;
2654 MethodInfo cmethod = method.CMethod;
2655 ParameterInfo error_parameter = null;
2657 if (method.ReturnType == null)
2658 throw new Exception (string.Format ("Method {0} in type {1} does not have a return type.", method.Name, method.Parent.Name));
2660 if (method.ReturnType.Value == "char*") {
2661 marshal_string_returntype = true;
2662 generate_wrapper = true;
2663 } else if (method.ReturnType.Value == "void") {
2664 is_void = true;
2667 // Check for parameters we can automatically generate code for.
2668 foreach (ParameterInfo parameter in cmethod.Parameters) {
2669 if (parameter.Name == "error" && parameter.ParameterType.Value == "MoonError*") {
2670 marshal_moonerror = true;
2671 generate_wrapper = true;
2672 error_parameter = parameter;
2676 name = method.CMethod.Name;
2677 managed_name = name;
2678 if (marshal_moonerror)
2679 managed_name = managed_name.Replace ("_with_error", "");
2681 returntype = method.ReturnType;
2682 // is_manually_defined = IsManuallyDefined (NativeMethods_cs, managed_name);
2683 contains_unknown_types = method.ContainsUnknownTypes;
2684 comment_out = contains_unknown_types;
2685 tabs = comment_out ? "\t\t// " : "\t\t";
2687 // if (is_manually_defined)
2688 // text.AppendLine ("\t\t// NOTE: There is a method in NativeMethod.cs with the same name.");
2690 if (contains_unknown_types)
2691 text.AppendLine ("\t\t// This method contains types the generator didn't know about. Fix the generator (find the method 'GetManagedType' in TypeReference.cs and add the missing case) and try again.");
2693 text.Append (tabs);
2694 text.Append ("[DllImport (\"");
2695 text.Append (library);
2696 if (generate_wrapper) {
2697 text.Append ("\", EntryPoint=\"");
2698 text.Append (name);
2700 text.AppendLine ("\")]");
2702 if (method.ReturnType.Value == "bool") {
2703 text.Append (tabs);
2704 text.AppendLine ("[return: MarshalAs (UnmanagedType.U1)]");
2705 } else if (method.ReturnType.Value == "gboolean") {
2706 text.Append (tabs);
2707 text.AppendLine ("[return: MarshalAs (UnmanagedType.Bool)]");
2710 // Always output the native signature too, makes it easier to check if the generation is wrong.
2711 text.Append ("\t\t// ");
2712 cmethod.WriteFormatted (text);
2713 text.AppendLine ();
2715 text.Append (tabs);
2716 text.Append (generate_wrapper ? "private " : "public ");
2717 text.Append ("extern static ");
2718 if (marshal_string_returntype)
2719 text.Append ("IntPtr");
2720 else
2721 returntype.Write (text, SignatureType.PInvoke, null);
2722 text.Append (" ");
2723 text.Append (name);
2724 if (generate_wrapper)
2725 text.Append ("_");
2726 cmethod.Parameters.Write (text, SignatureType.PInvoke, false);
2727 text.AppendLine (";");
2729 if (generate_wrapper) {
2730 text.Append (tabs);
2731 text.Append ("public static ");
2732 returntype.Write (text, SignatureType.Managed, null);
2733 text.Append (" ");
2734 text.Append (managed_name);
2736 foreach (ParameterInfo parameter in cmethod.Parameters)
2737 parameter.DisableWriteOnce = parameter.ManagedWrapperCode != null;
2739 if (error_parameter != null)
2740 error_parameter.DisableWriteOnce = true;
2742 cmethod.Parameters.Write (text, SignatureType.Managed, false);
2743 text.AppendLine ();
2745 text.Append (tabs);
2746 text.Append ("{");
2747 text.AppendLine ();
2749 text.Append (tabs);
2751 if (marshal_string_returntype) {
2752 text.AppendLine ("\tIntPtr result;");
2753 } else if (!is_void) {
2754 text.Append ("\t");
2755 returntype.Write (text, SignatureType.Managed, null);
2756 text.AppendLine (" result;");
2759 if (marshal_moonerror) {
2760 text.Append (tabs);
2761 text.AppendLine ("\tMoonError error;");
2764 text.Append (tabs);
2765 text.Append ("\t");
2766 if (!is_void)
2767 text.Append ("result = ");
2769 text.Append (cmethod.Name);
2770 text.Append ("_");
2771 cmethod.Parameters.Write (text, SignatureType.Managed, true);
2773 text.AppendLine (";");
2775 if (marshal_moonerror) {
2776 text.Append (tabs);
2777 text.AppendLine ("\tif (error.Number != 0)");
2779 text.Append (tabs);
2780 text.AppendLine ("\t\tthrow CreateManagedException (error);");
2783 if (marshal_string_returntype) {
2784 text.Append (tabs);
2785 text.AppendLine ("\tif (result == IntPtr.Zero)");
2786 text.Append (tabs);
2787 text.AppendLine ("\t\treturn null;");
2788 text.Append (tabs);
2789 text.AppendLine ("\tstring s = Marshal.PtrToStringAnsi (result);\t// *copy* unmanaged string");
2790 text.Append (tabs);
2791 if (!method.ReturnType.IsConst) {
2792 text.AppendLine ("\tMarshal.FreeHGlobal (result);\t\t\t// g_free the unmanaged string");
2793 text.Append (tabs);
2795 text.AppendLine ("\treturn s;");
2796 } else if (!is_void) {
2797 text.Append (tabs);
2798 text.AppendLine ("\treturn result;");
2801 text.Append (tabs);
2802 text.Append ("}");
2803 text.AppendLine ();
2808 static void RemoveExcludedSrcFiles (string srcdir, List<string> files)
2810 files.Remove (Path.Combine (srcdir, "cbinding.h"));
2811 files.Remove (Path.Combine (srcdir, "ptr.h"));