public static void Go(OutputWriter writer, BasePropertyDeclarationSyntax property, bool isProxy = false) { writer.WriteLine(); //TODO, doesnt ref make things slower ?, though it makes proprties behave as in c# var isInterface = property.Parent is InterfaceDeclarationSyntax; var getter = property.AccessorList.Accessors.SingleOrDefault( o => o.Keyword.RawKind == (decimal)SyntaxKind.GetKeyword); var setter = property.AccessorList.Accessors.SingleOrDefault( o => o.Keyword.RawKind == (decimal)SyntaxKind.SetKeyword); var isYield = getter != null && getter.DescendantNodes().OfType <YieldStatementSyntax>().Any(); var isStatic = property.Modifiers.Any(k => k.IsKind(SyntaxKind.StaticKeyword)); ITypeSymbol iface; ISymbol[] proxies; var name = MemberUtilities.GetMethodName(property, ref isInterface, out iface, out proxies); var modifiers = property.Modifiers; var propertySymbol = (IPropertySymbol)TypeProcessor.GetDeclaredSymbol(property); var type = propertySymbol.Type; var acccessmodifiers = MemberUtilities.GetAccessModifiers(property, isInterface || propertySymbol.IsAbstract); var typeString = TypeProcessor.ConvertType(type); var hasGetter = getter != null; var getterHasBody = hasGetter && getter.Body != null; var hasSetter = setter != null; var setterHasBody = hasSetter && setter.Body != null; var indexerDeclarationSyntax = property as IndexerDeclarationSyntax; var isindexer = indexerDeclarationSyntax != null; string getterbody = null; if (getterHasBody) { getterbody = Core.WriteBlock(getter.Body, false, writer.Indent + 2); if (!isProxy && isYield) { var namedTypeSymbol = propertySymbol.Type as INamedTypeSymbol; if (namedTypeSymbol != null) { // var iteratortype = namedTypeSymbol.TypeArguments[0]; // getterbody=String.Format("return new __IteratorBlock!({0})(delegate(__IteratorBlock!({0}) __iter){{ {1} }});", // TypeProcessor.ConvertType(iteratortype),getterbody); var className = propertySymbol.GetYieldClassName() + ( (((INamedTypeSymbol)propertySymbol.Type).TypeArguments.Any() && ((INamedTypeSymbol)propertySymbol.Type).TypeArguments[0].TypeKind == TypeKind.TypeParameter) ? "__G" : ""); // writer.WriteLine(accessString + returnTypeString + methodSignatureString + @params2 + constraints); //writer.OpenBrace(); if (!propertySymbol.IsStatic) { getterbody = writer.WriteIndentToString() + ("return new " + className + "(this);"); } else { getterbody = writer.WriteIndentToString() + ("return new " + className + "();"); } } } } string setterbody = null; if (setterHasBody) { setterbody = Core.WriteString(setter.Body, false, writer.Indent + 2); if (isindexer) { setterbody += writer.WriteIndentToString() + "return value;"; } else { if (hasGetter) { setterbody += writer.WriteIndentToString() + "return " + name + ";"; } } } if (getter == null && setter == null) { throw new Exception("Property must have either a get or a set"); } string isOverride; var fieldName = WriteAutoFieldName(writer, name, modifiers, isInterface, hasGetter, getterHasBody, hasSetter, setterHasBody, typeString, out isOverride, (property is IndexerDeclarationSyntax)); BracketedParameterListSyntax @params = null; if (indexerDeclarationSyntax != null) { @params = indexerDeclarationSyntax.ParameterList; } string parameters = null; if (@params != null) { parameters = WriteMethod.GetParameterListAsString(@params.Parameters, iface: proxies == null ? iface : null, writebraces: false); } WriteGetter(writer, isProxy, hasGetter, acccessmodifiers, typeString, name, proxies == null ? iface : null, getterHasBody, modifiers, isInterface, fieldName, getterbody, parameters, indexerDeclarationSyntax != null); WriteSetter(writer, isProxy, hasSetter, acccessmodifiers, name, typeString, proxies == null ? iface : null, isOverride, setterHasBody, modifiers, isInterface, fieldName, setterbody, parameters, isindexer, hasGetter); // if (!isindexer && !isInterface) //TODO: Find a better solution // { // var fieldacccessmodifiers = acccessmodifiers.Replace ("abstract", "").Replace ("virtual","").Replace("override",""); // // writer.WriteLine(fieldacccessmodifiers + "__Property!(" + typeString + ")" + name + ";"); // if (isStatic) // { // var staticWriter = new TempWriter (); // // staticWriter.WriteLine (name + String.Format (" = __Property!(" + typeString + ")(__ToDelegate(&set{0}), __ToDelegate(&get{0}));", name)); // Context.Instance.StaticInits.Add (staticWriter.ToString ()); // } // else // { // var instanceWriter = new TempWriter (); // // instanceWriter.WriteLine (name + String.Format (" = __Property!(" + typeString + ")((&set{0}), (&get{0}));", name)); // Context.Instance.InstanceInits.Add (instanceWriter.ToString ()); // } // } if (proxies != null) { foreach (var proxy in proxies) { if (indexerDeclarationSyntax == null) { setterbody = writer.WriteIndentToString() + name + "=" + "value" + ";"; getterbody = writer.WriteIndentToString() + "return " + name + ";"; } else { string parameters2 = ""; if (@params != null) { parameters2 = WriteMethod.GetParameterListAsString(@params.Parameters, iface: null, includeTypes: false, writebraces: false); // parameters2 = WriteMethod.GetParameterListAsString(@params.Parameters, iface: proxies == null ? iface : null, writebraces: false); } setterbody = writer.WriteIndentToString() + "return opIndexAssign(value," + parameters2 + ");";// + "=" + "value" + ";"; getterbody = writer.WriteIndentToString() + "return opIndex(" + parameters2 + ");"; } parameters = null; if (@params != null) { parameters = WriteMethod.GetParameterListAsString(@params.Parameters, iface: proxy.ContainingType, writebraces: false); } WriteGetter(writer, isProxy, hasGetter, acccessmodifiers, typeString, name, proxy.ContainingType, getterHasBody, modifiers, isInterface, fieldName, getterbody, parameters, isindexer); WriteSetter(writer, isProxy, hasSetter, acccessmodifiers, name, typeString, proxy.ContainingType, isOverride, setterHasBody, modifiers, isInterface, fieldName, setterbody, parameters, isindexer, hasGetter); } } }
public static void WriteIt(OutputWriter writer, MethodDeclarationSyntax method, bool isProxy = true, IEnumerable <ITypeSymbol> virtualGenericClasses = null) { var methodSymbol = (IMethodSymbol)TypeProcessor.GetDeclaredSymbol(method); var isYield = YieldChecker.HasYield(method);//method.DescendantNodes().OfType<YieldStatementSyntax>().Any(); writer.WriteLine(); var pinvokeAttributes = method.GetAttribute(Context.DllImport); var isInternalPInvoke = pinvokeAttributes == null && method.Modifiers.Any(SyntaxKind.ExternKeyword); //TODO: Improve partial class / method support -- partials classes work, methods need minor work ... if (method.Modifiers.Any(SyntaxKind.PartialKeyword) && method.Body == null) { //We only want to render out one of the two partial methods. If there's another, skip this one. if (Context.Instance.Partials.SelectMany(o => o.Syntax.As <ClassDeclarationSyntax>().Members) .OfType <MethodDeclarationSyntax>() .Except(method).Any(o => o.Identifier.Text == method.Identifier.Text)) { return; } } var accessString = ""; var isInterface = method.Parent is InterfaceDeclarationSyntax; ITypeSymbol iface; ISymbol[] proxies; var methodName = MemberUtilities.GetMethodName(method, ref isInterface, out iface, out proxies); // var originalMethodName = methodName; var containingType = iface == null ? methodSymbol.ContainingType : iface; if (virtualGenericClasses != null) { methodName = TypeProcessor.ConvertType(containingType, false, false, false).Replace(".", "_") + "_" + methodName; accessString = "public static final "; } else if (methodName == "Main" /*&& method.Modifiers.Any(SyntaxKind.PublicKeyword)*/ && method.Modifiers.Any(SyntaxKind.StaticKeyword)) { accessString = ("public "); accessString += ("static "); var methodCall = methodSymbol.ContainingNamespace.FullName() + "." + methodSymbol.ContainingType.FullName() + "." + methodName + (method.ParameterList.Parameters.Count < 1 ? "();" : "(null);"); //: "(new Array_T!(String)(args));"); // for now args not supported Context.Instance.EntryMethod = methodCall; } else { accessString = MemberUtilities.GetAccessModifiers(method, isInterface || methodSymbol.IsAbstract); } var returnTypeString = TypeProcessor.ConvertType(method.ReturnType, true) + " "; var methodSignatureString = ""; if (method.ReturnType.ToString() == "void") { returnTypeString = ("void "); } methodSignatureString += methodName; var genericParameters = ""; if (method.TypeParameterList != null) { var genericArgs = method.TypeParameterList.Parameters.ToList(); // if (genericArgs.Count > 0) // { // writer.Write("( "); // writer.Write(string.Join(" , ", genericArgs.Select(o => " " + o))); // writer.Write(" )\r\n"); // } if (genericArgs.Count > 0) // && !methodSymbol.ContainingType.IsGenericType) // doesnt matter { genericParameters += ("("); genericParameters += (string.Join(",", genericArgs.Select(o => o))); genericParameters += (")"); } } methodSignatureString += genericParameters; var @params = GetParameterListAsString(method.ParameterList.Parameters, iface: proxies == null ? iface : null, genericClass: virtualGenericClasses != null ? containingType : null); // if (virtualGenericClasses != null) // { // @params = TypeProcessor.ConvertType() + ", " + @params; // } string constraints = GetMethodConstraints(method); if (isInterface || method.Modifiers.Any(SyntaxKind.AbstractKeyword)) { writer.WriteLine(accessString + returnTypeString + methodSignatureString + @params + constraints + ";"); return; } writer.WriteLine(accessString + returnTypeString + methodSignatureString + @params + constraints); writer.OpenBrace(); if (isProxy) { @params = GetParameterListAsString(method.ParameterList.Parameters, includeTypes: false); if (virtualGenericClasses != null) { /* * public final static void Program_IBase_GenericVirtual_Dispatch(T)(Program.IBase aobj) * { * Object obj = cast(Object) aobj; * if((typeid(obj)==typeid(Program.B))) * (cast(Program.B)obj).GenericVirtual!(T)(); * if((typeid(obj)==typeid(Program.A))) * (cast(Program.A)obj).GenericVirtual!(T)(); * * } */ writer.WriteLine("NObject ___obj = cast(NObject)__obj;"); foreach (var virtualGenericClass in virtualGenericClasses) { var className = TypeProcessor.ConvertType(virtualGenericClass); writer.WriteLine("if(typeid(___obj)==typeid({0}))", className); if (method.ReturnType.ToString() == "void") { writer.WriteLine("(cast({0})___obj)." + originalMethodName + "!" + genericParameters + @params + ";", className); } else { writer.WriteLine("return (cast({0})___obj)." + methodSignatureString + "!" + genericParameters + ";", className); } } } else { if (method.ReturnType.ToString() == "void") { writer.WriteLine("__Value." + methodName + @params + ";"); } else { writer.WriteLine("return __Value." + methodName + @params + ";"); } } } else { if (!isProxy && isYield) { var namedTypeSymbol = methodSymbol.ReturnType as INamedTypeSymbol; if (namedTypeSymbol != null) { // var iteratortype = namedTypeSymbol.TypeArguments[0]; var className = methodSymbol.GetYieldClassName() + ( (((INamedTypeSymbol)methodSymbol.ReturnType).TypeArguments.Any() && ((INamedTypeSymbol)methodSymbol.ReturnType).TypeArguments[0].TypeKind == TypeKind.TypeParameter) ? "__G" : ""); methodSignatureString = methodName + genericParameters; if (!String.IsNullOrEmpty(genericParameters)) { className = className + "!" + genericParameters; } var @params2 = GetParameterListAsString(method.ParameterList.Parameters, iface: methodSymbol.ContainingType); var @params3 = GetParameterListAsString(method.ParameterList.Parameters, iface: null, includeTypes: false, writebraces: false); // writer.WriteLine(accessString + returnTypeString + methodSignatureString + @params2 + constraints); //writer.OpenBrace(); if (!methodSymbol.IsStatic) { if (method.ParameterList.Parameters.Count > 0) { writer.WriteLine("return new " + className + "(this," + @params3 + ");"); } else { writer.WriteLine("return new " + className + "(this);"); } } else { writer.WriteLine("return new " + className + "(" + @params3 + ");"); } } } else if (method.Body != null) { foreach (var statement in method.Body.Statements) { Core.Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, method.Body.DescendantTrivia()); } if (pinvokeAttributes != null) { WritePInvokeMethodBody.Go(writer, methodName, methodSymbol, pinvokeAttributes); } if (isInternalPInvoke) { WritePInvokeMethodBody.Go(writer, methodName, methodSymbol, null); } if (!isProxy && isYield) { //writer.WriteLine("});"); } } writer.CloseBrace(); if (proxies != null) { foreach (var proxy in proxies) { //Need to write proxy signature here ... methodSignatureString = methodName + genericParameters; var @params2 = GetParameterListAsString(method.ParameterList.Parameters, iface: proxy.ContainingType); var @params3 = GetParameterListAsString(method.ParameterList.Parameters, iface: null, includeTypes: false); writer.WriteLine(accessString + returnTypeString + methodSignatureString + @params2 + constraints); writer.OpenBrace(); if (method.ReturnType.ToString() == "void") { writer.WriteLine("" + methodName + @params3 + ";"); } else { writer.WriteLine("return " + methodName + @params3 + ";"); } writer.CloseBrace(); } } }