1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
5
using System.Collections.Generic;
7
using System.Diagnostics;
8
using System.Reflection;
10
using NRefactoryASTGenerator.Ast;
11
using ICSharpCode.EasyCodeDom;
13
namespace NRefactoryASTGenerator
17
public const string VisitPrefix = "Visit";
19
static readonly string[] lineEndings = { "\r\n", "\r", "\n" };
21
public static void Main(string[] args)
23
string directory = "../../../Project/Src/Ast/";
24
string visitorsDir = "../../../Project/Src/Visitors/";
25
Debug.WriteLine("AST Generator running...");
26
if (!File.Exists(directory + "INode.cs")) {
27
Debug.WriteLine("did not find output directory");
30
if (!File.Exists(visitorsDir + "AbstractAstTransformer.cs")) {
31
Debug.WriteLine("did not find visitor output directory");
35
List<Type> nodeTypes = new List<Type>();
36
foreach (Type type in typeof(MainClass).Assembly.GetTypes()) {
37
if (type.IsClass && typeof(INode).IsAssignableFrom(type)) {
41
nodeTypes.Sort(delegate(Type a, Type b) { return a.Name.CompareTo(b.Name); });
43
CodeCompileUnit ccu = new CodeCompileUnit();
44
CodeNamespace cns = ccu.AddNamespace("ICSharpCode.NRefactory.Ast");
45
cns.AddImport("System");
46
cns.AddImport("System.Collections.Generic");
47
foreach (Type type in nodeTypes) {
48
if (type.GetCustomAttributes(typeof(CustomImplementationAttribute), false).Length == 0) {
49
CodeTypeDeclaration ctd = cns.AddType(type.Name);
50
if (type.IsAbstract) {
51
ctd.TypeAttributes |= TypeAttributes.Abstract;
53
ctd.BaseTypes.Add(new CodeTypeReference(type.BaseType.Name));
55
ProcessType(type, ctd);
57
foreach (object o in type.GetCustomAttributes(false)) {
58
if (o is TypeImplementationModifierAttribute) {
59
(o as TypeImplementationModifierAttribute).ModifyImplementation(cns, ctd, type);
63
if (!type.IsAbstract) {
64
CodeMemberMethod method = new CodeMemberMethod();
65
method.Name = "AcceptVisitor";
66
method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
67
method.Parameters.Add(new CodeParameterDeclarationExpression("IAstVisitor", "visitor"));
68
method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "data"));
69
method.ReturnType = new CodeTypeReference(typeof(object));
70
CodeExpression ex = new CodeVariableReferenceExpression("visitor");
71
ex = new CodeMethodInvokeExpression(ex, VisitPrefix + ctd.Name,
72
new CodeThisReferenceExpression(),
73
new CodeVariableReferenceExpression("data"));
74
method.Statements.Add(new CodeMethodReturnStatement(ex));
75
ctd.Members.Add(method);
77
method = new CodeMemberMethod();
78
method.Name = "ToString";
79
method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
80
method.ReturnType = new CodeTypeReference(typeof(string));
81
method.Statements.Add(new CodeMethodReturnStatement(CreateToString(type)));
82
ctd.Members.Add(method);
87
System.CodeDom.Compiler.CodeGeneratorOptions settings = new System.CodeDom.Compiler.CodeGeneratorOptions();
88
settings.IndentString = "\t";
89
settings.VerbatimOrder = true;
91
using (StringWriter writer = new StringWriter()) {
92
new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
93
File.WriteAllText(directory + "Generated.cs", NormalizeNewLines(writer));
96
ccu = new CodeCompileUnit();
97
cns = ccu.AddNamespace("ICSharpCode.NRefactory");
98
cns.AddImport("System");
99
cns.AddImport("ICSharpCode.NRefactory.Ast");
100
cns.Types.Add(CreateAstVisitorInterface(nodeTypes));
102
using (StringWriter writer = new StringWriter()) {
103
new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
104
File.WriteAllText(visitorsDir + "../IAstVisitor.cs", NormalizeNewLines(writer));
107
ccu = new CodeCompileUnit();
108
cns = ccu.AddNamespace("ICSharpCode.NRefactory.Visitors");
109
cns.AddImport("System");
110
cns.AddImport("System.Collections.Generic");
111
cns.AddImport("System.Diagnostics");
112
cns.AddImport("ICSharpCode.NRefactory.Ast");
113
cns.Types.Add(CreateAstVisitorClass(nodeTypes, false));
115
using (StringWriter writer = new StringWriter()) {
116
new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
117
File.WriteAllText(visitorsDir + "AbstractAstVisitor.cs", NormalizeNewLines(writer));
120
ccu = new CodeCompileUnit();
121
cns = ccu.AddNamespace("ICSharpCode.NRefactory.Visitors");
122
cns.AddImport("System");
123
cns.AddImport("System.Collections.Generic");
124
cns.AddImport("System.Diagnostics");
125
cns.AddImport("ICSharpCode.NRefactory.Ast");
126
cns.Types.Add(CreateAstVisitorClass(nodeTypes, true));
128
using (StringWriter writer = new StringWriter()) {
129
new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
130
File.WriteAllText(visitorsDir + "AbstractAstTransformer.cs", NormalizeNewLines(writer));
133
ccu = new CodeCompileUnit();
134
cns = ccu.AddNamespace("ICSharpCode.NRefactory.Visitors");
135
cns.AddImport("System");
136
cns.AddImport("ICSharpCode.NRefactory.Ast");
137
cns.Types.Add(CreateNodeTrackingAstVisitorClass(nodeTypes));
139
using (StringWriter writer = new StringWriter()) {
140
new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
141
// CodeDom cannot output "sealed", so we need to use this hack:
142
File.WriteAllText(visitorsDir + "NodeTrackingAstVisitor.cs",
143
NormalizeNewLines(writer).Replace("public override object", "public sealed override object"));
146
//NotImplementedAstVisitor
147
ccu = new CodeCompileUnit();
148
cns = ccu.AddNamespace("ICSharpCode.NRefactory.Visitors");
149
cns.AddImport("System");
150
cns.AddImport("ICSharpCode.NRefactory.Ast");
151
cns.Types.Add(CreateNotImplementedAstVisitorClass(nodeTypes));
153
using (StringWriter writer = new StringWriter()) {
154
new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
155
File.WriteAllText(visitorsDir + "NotImplementedAstVisitor.cs", NormalizeNewLines(writer));
157
Debug.WriteLine("AST Generator done!");
159
Debug.WriteLine("start keyword list generation...");
161
KeywordGenerator.Generate();
163
Debug.WriteLine("keyword list generation done!");
166
static string NormalizeNewLines(StringWriter writer)
168
return string.Join(Environment.NewLine, writer.ToString().Split(lineEndings, StringSplitOptions.None));
171
static CodeTypeDeclaration CreateAstVisitorInterface(List<Type> nodeTypes)
173
CodeTypeDeclaration td = new CodeTypeDeclaration("IAstVisitor");
174
td.IsInterface = true;
176
foreach (Type t in nodeTypes) {
178
EasyMethod m = td.AddMethod(typeof(object), VisitPrefix + t.Name);
179
m.AddParameter(ConvertType(t), GetFieldName(t.Name));
180
m.AddParameter(typeof(object), "data");
186
static CodeTypeDeclaration CreateAstVisitorClass(List<Type> nodeTypes, bool transformer)
188
CodeTypeDeclaration td = new CodeTypeDeclaration(transformer ? "AbstractAstTransformer" : "AbstractAstVisitor");
189
td.TypeAttributes = TypeAttributes.Public | TypeAttributes.Abstract;
190
td.BaseTypes.Add(new CodeTypeReference("IAstVisitor"));
194
"The AbstractAstTransformer will iterate through the whole AST,\n " +
195
"just like the AbstractAstVisitor. However, the AbstractAstTransformer allows\n " +
196
"you to modify the AST at the same time: It does not use 'foreach' internally,\n " +
197
"so you can add members to collections of parents of the current node (but\n " +
198
"you cannot insert or delete items as that will make the index used invalid).\n " +
199
"You can use the methods ReplaceCurrentNode and RemoveCurrentNode to replace\n " +
200
"or remove the current node, totally independent from the type of the parent node.";
201
Easy.AddSummary(td, comment);
203
CodeMemberField field = td.AddField(Easy.TypeRef("Stack", "INode"), "nodeStack");
204
field.InitExpression = Easy.New(field.Type);
207
CodeExpression nodeStack = Easy.Var("nodeStack");
208
CodeMemberProperty p = new CodeMemberProperty();
209
p.Name = "CurrentNode";
210
p.Type = new CodeTypeReference("INode");
211
p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
212
p.GetStatements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("currentNode")));
213
p.SetStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("currentNode"),
214
new CodePropertySetValueReferenceExpression()));
218
EasyMethod m = td.AddMethod("ReplaceCurrentNode");
219
m.AddParameter(Easy.TypeRef("INode"), "newNode");
220
m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Pop"));
221
m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Push", Easy.Var("newNode")));
223
m = td.AddMethod("RemoveCurrentNode");
224
m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Pop"));
225
m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Push", Easy.Null));
228
foreach (Type type in nodeTypes) {
229
if (!type.IsAbstract) {
230
EasyMethod m = td.AddMethod(typeof(object), VisitPrefix + type.Name);
231
m.Attributes = MemberAttributes.Public;
232
m.AddParameter(ConvertType(type), GetFieldName(type.Name));
233
m.AddParameter(typeof(object), "data");
235
List<CodeStatement> assertions = new List<CodeStatement>();
236
string varVariableName = GetFieldName(type.Name);
237
CodeExpression var = Easy.Var(varVariableName);
238
assertions.Add(AssertIsNotNull(var));
240
AddFieldVisitCode(m, type, var, assertions, transformer);
242
if (type.GetCustomAttributes(typeof(HasChildrenAttribute), true).Length > 0) {
244
m.Statements.Add(new CodeSnippetStatement(CreateTransformerLoop(varVariableName + ".Children", "INode")));
245
m.Body.Return(Easy.Null);
247
m.Body.Return(var.InvokeMethod("AcceptChildren", Easy.This, Easy.Var("data")));
250
CodeExpressionStatement lastStatement = null;
251
if (m.Statements.Count > 0) {
252
lastStatement = m.Statements[m.Statements.Count - 1] as CodeExpressionStatement;
254
if (lastStatement != null) {
255
m.Statements.RemoveAt(m.Statements.Count - 1);
256
m.Body.Return(lastStatement.Expression);
258
m.Body.Return(Easy.Null);
262
for (int i = 0; i < assertions.Count; i++) {
263
m.Statements.Insert(i, assertions[i]);
270
static void AddFieldVisitCode(EasyMethod m, Type type, CodeExpression var, List<CodeStatement> assertions, bool transformer)
273
if (type.BaseType != typeof(StatementWithEmbeddedStatement)) {
274
AddFieldVisitCode(m, type.BaseType, var, assertions, transformer);
276
foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)) {
277
AddVisitCode(m, field, var, assertions, transformer);
279
if (type.BaseType == typeof(StatementWithEmbeddedStatement)) {
280
AddFieldVisitCode(m, type.BaseType, var, assertions, transformer);
285
static CodeStatement AssertIsNotNull(CodeExpression expr)
287
return new CodeExpressionStatement(
288
Easy.Type("Debug").InvokeMethod("Assert",
290
CodeBinaryOperatorType.IdentityInequality,
295
static string GetCode(CodeExpression ex)
297
using (StringWriter writer = new StringWriter()) {
298
new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromExpression(ex, writer, null);
299
return writer.ToString();
303
static string CreateTransformerLoop(string collection, string typeName)
306
"\t\t\tfor (int i = 0; i < " + collection + ".Count; i++) {\n" +
307
"\t\t\t\t" + typeName + " o = " + collection + "[i];\n" +
308
"\t\t\t\tDebug.Assert(o != null);\n" +
309
"\t\t\t\tnodeStack.Push(o);\n" +
310
"\t\t\t\to.AcceptVisitor(this, data);\n" +
312
? "\t\t\t\to = nodeStack.Pop();\n"
313
: "\t\t\t\to = (" + typeName + ")nodeStack.Pop();\n") +
314
"\t\t\t\tif (o == null)\n" +
315
"\t\t\t\t\t" + collection + ".RemoveAt(i--);\n" +
317
"\t\t\t\t\t" + collection + "[i] = o;\n" +
321
static bool AddVisitCode(EasyMethod m, FieldInfo field, CodeExpression var, List<CodeStatement> assertions, bool transformer)
323
CodeExpression prop = var.Property(GetPropertyName(field.Name));
324
CodeExpression nodeStack = Easy.Var("nodeStack");
325
if (field.FieldType.FullName.StartsWith("System.Collections.Generic.List")) {
326
Type elType = field.FieldType.GetGenericArguments()[0];
327
if (!typeof(INode).IsAssignableFrom(elType))
329
assertions.Add(AssertIsNotNull(prop));
332
code = CreateTransformerLoop(GetCode(prop), ConvertType(elType).BaseType);
335
"\t\t\tforeach (" + ConvertType(elType).BaseType + " o in " + GetCode(prop) + ") {\n" +
336
"\t\t\t\tDebug.Assert(o != null);\n" +
337
"\t\t\t\to.AcceptVisitor(this, data);\n" +
340
m.Statements.Add(new CodeSnippetStatement(code));
343
if (!typeof(INode).IsAssignableFrom(field.FieldType))
345
assertions.Add(AssertIsNotNull(prop));
347
m.Statements.Add(nodeStack.InvokeMethod("Push", prop));
349
m.Statements.Add(prop.InvokeMethod("AcceptVisitor",
353
m.Body.Assign(prop, nodeStack.InvokeMethod("Pop").CastTo(ConvertType(field.FieldType)));
358
static CodeExpression CreateToString(Type type)
360
CodeMethodInvokeExpression ie = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(string)),
362
CodePrimitiveExpression prim = new CodePrimitiveExpression();
363
ie.Parameters.Add(prim);
364
string text = "[" + type.Name;
367
foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)) {
368
text += " " + GetPropertyName(field.Name) + "={" + index.ToString() + "}";
370
if (typeof(System.Collections.ICollection).IsAssignableFrom(field.FieldType)) {
371
ie.Parameters.Add(new CodeSnippetExpression("GetCollectionString(" + GetPropertyName(field.Name) + ")"));
373
ie.Parameters.Add(new CodeVariableReferenceExpression(GetPropertyName(field.Name)));
376
type = type.BaseType;
377
} while (type != null);
378
prim.Value = text + "]";
379
if (ie.Parameters.Count == 1)
383
// return String.Format("[AnonymousMethodExpression: Parameters={0} Body={1}]",
384
// GetCollectionString(Parameters),
388
static void ProcessType(Type type, CodeTypeDeclaration ctd)
390
foreach (FieldInfo field in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic)) {
391
ctd.AddField(ConvertType(field.FieldType), field.Name).Attributes = 0;
393
foreach (FieldInfo field in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic)) {
394
EasyProperty p = ctd.AddProperty(ConvertType(field.FieldType), GetPropertyName(field.Name));
395
p.Getter.Return(Easy.Var(field.Name));
397
if (field.FieldType.IsValueType)
398
ex = new CodePropertySetValueReferenceExpression();
400
ex = GetDefaultValue("value", field);
401
p.Setter.Assign(Easy.Var(field.Name), ex);
402
if (typeof(INode).IsAssignableFrom(field.FieldType)) {
403
if (typeof(INullable).IsAssignableFrom(field.FieldType)) {
404
p.SetStatements.Add(new CodeSnippetStatement("\t\t\t\tif (!" +field.Name+".IsNull) "+field.Name+".Parent = this;"));
406
p.SetStatements.Add(new CodeSnippetStatement("\t\t\t\t"+field.Name+".Parent = this;"));
410
foreach (ConstructorInfo ctor in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
411
CodeConstructor c = new CodeConstructor();
413
c.Attributes = MemberAttributes.Family;
415
c.Attributes = MemberAttributes.Public;
417
ConstructorInfo baseCtor = GetBaseCtor(type);
418
foreach(ParameterInfo param in ctor.GetParameters()) {
419
c.Parameters.Add(new CodeParameterDeclarationExpression(ConvertType(param.ParameterType),
421
if (baseCtor != null && Array.Exists(baseCtor.GetParameters(), delegate(ParameterInfo p) { return param.Name == p.Name; }))
423
c.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression(GetPropertyName(param.Name)),
424
new CodeVariableReferenceExpression(param.Name)));
426
if (baseCtor != null) {
427
foreach(ParameterInfo param in baseCtor.GetParameters()) {
428
c.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(param.Name));
431
// initialize fields that were not initialized by parameter
432
foreach (FieldInfo field in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic)) {
433
if (field.FieldType.IsValueType && field.FieldType != typeof(Location))
435
if (Array.Exists(ctor.GetParameters(), delegate(ParameterInfo p) { return field.Name == p.Name; }))
437
c.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression(field.Name),
438
GetDefaultValue(null, field)));
443
internal static ConstructorInfo GetBaseCtor(Type type)
445
ConstructorInfo[] list = type.BaseType.GetConstructors();
446
if (list.Length == 0)
452
internal static CodeExpression GetDefaultValue(string inputVariable, FieldInfo field)
455
// get default value:
456
if (field.FieldType == typeof(string)) {
458
if (field.GetCustomAttributes(typeof(QuestionMarkDefaultAttribute), false).Length > 0) {
459
if (inputVariable == null)
460
return new CodePrimitiveExpression("?");
462
return new CodeSnippetExpression("string.IsNullOrEmpty(" + inputVariable + ") ? \"?\" : " + inputVariable);
464
} else if (field.FieldType.FullName.StartsWith("System.Collections.Generic.List")) {
465
code = "new List<" + field.FieldType.GetGenericArguments()[0].Name + ">()";
466
} else if (field.FieldType == typeof(Location)) {
467
code = "Location.Empty";
469
code = field.FieldType.Name + ".Null";
471
if (inputVariable != null) {
472
code = inputVariable + " ?? " + code;
474
return new CodeSnippetExpression(code);
477
internal static string GetFieldName(string typeName)
479
return char.ToLower(typeName[0]) + typeName.Substring(1);
482
internal static string GetPropertyName(string fieldName)
484
return char.ToUpper(fieldName[0]) + fieldName.Substring(1);
487
internal static CodeTypeReference ConvertType(Type type)
489
if (type.IsGenericType && !type.IsGenericTypeDefinition) {
490
CodeTypeReference tr = ConvertType(type.GetGenericTypeDefinition());
491
foreach (Type subType in type.GetGenericArguments()) {
492
tr.TypeArguments.Add(ConvertType(subType));
495
} else if (type.FullName.StartsWith("NRefactory") || type.FullName.StartsWith("System.Collections")) {
496
if (type.Name == "Attribute")
497
return new CodeTypeReference("ICSharpCode.NRefactory.Ast.Attribute");
498
return new CodeTypeReference(type.Name);
500
return new CodeTypeReference(type);
504
static CodeTypeDeclaration CreateNodeTrackingAstVisitorClass(List<Type> nodeTypes)
506
CodeTypeDeclaration td = new CodeTypeDeclaration("NodeTrackingAstVisitor");
507
td.TypeAttributes = TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Abstract;
508
td.BaseTypes.Add(new CodeTypeReference("AbstractAstVisitor"));
510
string comment = "<summary>\n " +
511
"The NodeTrackingAstVisitor will iterate through the whole AST,\n " +
512
"just like the AbstractAstVisitor, and calls the virtual methods\n " +
513
"BeginVisit and EndVisit for each node being visited.\n " +
515
td.Comments.Add(new CodeCommentStatement(comment, true));
516
comment = "<remarks>\n " +
517
"base.Visit(node, data) calls this.TrackedVisit(node, data), so if\n " +
518
"you want to visit child nodes using the default visiting behaviour,\n " +
519
"use base.TrackedVisit(parentNode, data).\n " +
521
td.Comments.Add(new CodeCommentStatement(comment, true));
523
EasyMethod m = td.AddMethod("BeginVisit");
524
m.Attributes = MemberAttributes.Family;
525
m.AddParameter(Easy.TypeRef("INode"), "node");
527
m = td.AddMethod("EndVisit");
528
m.Attributes = MemberAttributes.Family;
529
m.AddParameter(Easy.TypeRef("INode"), "node");
531
foreach (Type type in nodeTypes) {
532
if (!type.IsAbstract) {
534
m = td.AddMethod(typeof(object), VisitPrefix + type.Name);
535
m.Attributes = MemberAttributes.Public | MemberAttributes.Override;
536
m.AddParameter(ConvertType(type), GetFieldName(type.Name));
537
m.AddParameter(new CodeTypeReference(typeof(object)), "data");
539
CodeExpression var = Easy.Var(GetFieldName(type.Name));
541
m.Body.InvokeMethod(Easy.This, "BeginVisit", var);
542
m.Body.DeclareVariable(typeof(object), "result").InitExpression
543
= Easy.This.InvokeMethod("TrackedVisit" + type.Name, var, Easy.Var("data"));
544
m.Body.InvokeMethod(Easy.This, "EndVisit", var);
545
m.Body.Return(Easy.Var("result"));
549
foreach (Type type in nodeTypes) {
550
if (!type.IsAbstract) {
552
m = td.AddMethod(typeof(object), "TrackedVisit" + type.Name);
553
m.Attributes = MemberAttributes.Public;
554
m.AddParameter(ConvertType(type), GetFieldName(type.Name));
555
m.AddParameter(new CodeTypeReference(typeof(object)), "data");
557
m.Body.Return(Easy.Base.InvokeMethod(VisitPrefix + type.Name, Easy.Var(GetFieldName(type.Name)), Easy.Var("data")));
564
static CodeTypeDeclaration CreateNotImplementedAstVisitorClass(List<Type> nodeTypes)
566
CodeTypeDeclaration td = new CodeTypeDeclaration("NotImplementedAstVisitor");
567
td.TypeAttributes = TypeAttributes.Public | TypeAttributes.Class;
568
td.BaseTypes.Add(new CodeTypeReference("IAstVisitor"));
570
string comment = "<summary>\n " +
571
"IAstVisitor implementation that always throws NotImplementedExceptions.\n " +
573
td.Comments.Add(new CodeCommentStatement(comment, true));
575
foreach (Type type in nodeTypes) {
576
if (!type.IsAbstract) {
578
EasyMethod m = td.AddMethod(typeof(object), VisitPrefix + type.Name);
579
m.Attributes = MemberAttributes.Public;
580
m.AddParameter(ConvertType(type), GetFieldName(type.Name));
581
m.AddParameter(new CodeTypeReference(typeof(object)), "data");
583
m.Body.Throw(Easy.New(typeof(NotImplementedException), Easy.Prim(type.Name)));