public static void WriteIt(OutputWriter writer, MethodDeclarationSyntax method, bool isProxy = true) { writer.WriteLine(); var methodSymbol = (IMethodSymbol)TypeProcessor.GetDeclaredSymbol(method); var methodName = OverloadResolver.MethodName(methodSymbol); var pinvokeAttributes = method.GetAttribute(Context.DllImport); // Fix this to actually look for the type, not just by name ... //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.ValueText == method.Identifier.ValueText)) { return; } } bool isoverride = ShouldUseOverrideKeyword(method, methodSymbol); var accessString = ""; if (isoverride) { accessString += (" override "); } var isInterface = method.Parent is InterfaceDeclarationSyntax; 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 { if (method.Modifiers.Any(SyntaxKind.PublicKeyword) || method.Modifiers.Any(SyntaxKind.InternalKeyword) || method.Modifiers.Any(SyntaxKind.ProtectedKeyword) || method.Modifiers.Any(SyntaxKind.AbstractKeyword) || isInterface) { accessString += ("public "); } if (method.Modifiers.Any(SyntaxKind.PrivateKeyword)) { accessString += ("private "); } // if (method.Modifiers.Any(SyntaxKind.VirtualKeyword) || isInterface) // writer.Write("virtual "); // if (!(method.Modifiers.Any (SyntaxKind.VirtualKeyword) || (method.Modifiers.Any (SyntaxKind.AbstractKeyword) || isInterface || isoverride))) { // writer.Write(" final "); // } if (method.Modifiers.Any(SyntaxKind.AbstractKeyword)) { accessString += (" abstract "); } if (method.Modifiers.Any(SyntaxKind.StaticKeyword)) { accessString += ("static "); } } // if (isInterface) // { // writer.IsInterface = true; // } var returnTypeString = TypeProcessor.ConvertType(method.ReturnType) + " "; var methodSignatureString = ""; if (method.ReturnType.ToString() == "void") { returnTypeString = ("void "); } else // bool returnsVoid = method.ReturnType.ToString() == "void"; //if (!returnsVoid) { var typeSymbol = TypeProcessor.GetTypeInfo(method.ReturnType).Type; // var isPtr = typeSymbol != null && (typeSymbol.IsValueType || typeSymbol.TypeKind == TypeKind.TypeParameter) ? "" : ""; // var typeString = TypeProcessor.ConvertType(method.ReturnType) + isPtr + " "; // writer.Write(typeString); // writer.HeaderWriter.Write(typeString); var isPtr = typeSymbol != null && (!typeSymbol.IsValueType || typeSymbol.TypeKind == TypeKind.TypeParameter); } if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface || Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol)) { methodName = Regex.Replace( TypeProcessor.ConvertType(methodSymbol.ContainingType.ConstructedFrom) + "_" + methodName, @" ?!\(.*?\)", string.Empty); } if (methodName.Contains(".")) // Explicit Interface method { // methodName = methodName.SubstringAfterLast('.'); methodName = methodName.Replace('.', '_'); } // var typenameI = Regex.Replace (TypeProcessor.ConvertType (interfaceMethod.ContainingType), @" ?!\(.*?\)", string.Empty); var interfaceMethods = methodSymbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(methodName)).ToArray(); ISymbol interfaceMethod = interfaceMethods.FirstOrDefault( o => methodSymbol.ContainingType.FindImplementationForInterfaceMember(o) == methodSymbol); if (interfaceMethod == null) { //TODO: fix this for virtual method test 7, seems roslyn cannot deal with virtual // overrides of interface methods ... so i'll provide a kludge if (!method.Modifiers.Any(SyntaxKind.NewKeyword)) { interfaceMethod = interfaceMethods.FirstOrDefault(k => CompareMethods(k as IMethodSymbol, methodSymbol)); } } if (interfaceMethod != null) // && CompareMethods(interfaceMethod ,methodSymbol)) { { //This is an interface method //TO if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array) { methodSignatureString += (""); } else { var typenameI = Regex.Replace(TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom), @" ?!\(.*?\)", string.Empty); //TODO: we should be able to get the original interface name, or just remove all generics from this if (typenameI.Contains('.')) { typenameI = typenameI.SubstringAfterLast('.'); } methodName = (typenameI + "_") + methodName; } } // var explicitHeaderNAme = ""; //FIX ME: To support explicits, all method calls are going to be prequalified with the interface name, lets just hope we dont have similar interfaces // // if (methodSymbol.MethodKind == MethodKind.ExplicitInterfaceImplementation) // { // // var implementations = methodSymbol.ExplicitInterfaceImplementations[0]; // if (implementations != null) // { // // explicitHeaderNAme = implementations.Name; // methodName = TypeProcessor.ConvertType(implementations.ReceiverType) + "_" +implementations.Name; //Explicit fix ? // // // writer.Write(methodSymbol.ContainingType + "." + methodName); // //Looks like internal classes are not handled properly here ... // } // } // methodName = methodName.Replace(methodSymbol.ContainingNamespace.FullName() + ".", methodSymbol.ContainingNamespace.FullName().Replace(".", "::") + "::"); // (methodSymbol as).Is // (methodSymbol as Microsoft.CodeAnalysis.CSharp.Symbols.SourceMethodSymbol); if (method.Modifiers.Any(SyntaxKind.NewKeyword)) { methodName += "_"; } // writer.Write( TypeProcessor.ConvertType(methodSymbol.ContainingType)+ "." + methodName); //Dealting with explicit VMT7 // writer.Write(!String.IsNullOrEmpty(explicitHeaderNAme)? explicitHeaderNAme : methodName); // writer.Write(methodName); methodSignatureString += methodName; 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 { methodSignatureString += ("("); methodSignatureString += (string.Join(",", genericArgs.Select(o => " " + o))); methodSignatureString += (")"); } } var @params = GetParameterListAsString(method.ParameterList); var constraints = ""; if (method.ConstraintClauses.Count > 0) { constraints += (" if ("); bool isFirst = true; foreach (var constraint in method.ConstraintClauses) { foreach (var condition in constraint.Constraints) { string dlangCondition = condition.ToString(); if (dlangCondition == "new()") { continue; } if (dlangCondition == "class") // TODO: is there a better way to do this ? { dlangCondition = "NObject"; } if (dlangCondition == "struct") { constraints += ((isFirst ? "" : "&&") + " !is(" + constraint.Name + " : NObject)"); } else { constraints += ((isFirst ? "" : "&&") + " is(" + constraint.Name + " : " + dlangCondition + ")"); } isFirst = false; // Console.WriteLine (condition); } } constraints += (")"); } 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, false); if (method.ReturnType.ToString() == "void") { writer.WriteLine("Value." + methodName + @params + ";"); } else { writer.WriteLine("return Value." + methodName + @params + ";"); } } 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); } } writer.CloseBrace(); }
public static void Go(OutputWriter writer, InvocationExpressionSyntax invocationExpression) { var symbolInfo = TypeProcessor.GetSymbolInfo(invocationExpression); var expressionSymbol = TypeProcessor.GetSymbolInfo(invocationExpression.Expression); var symbol = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault(); // Resolution error if (symbol == null) { writer.WriteLine("/*" + invocationExpression.ToFullString() + " //SharpNative Failed To Get Symbol */"); } var methodSymbol = symbol.OriginalDefinition.As <IMethodSymbol>().UnReduce(); var memberReferenceExpressionOpt = invocationExpression.Expression as MemberAccessExpressionSyntax; var firstParameter = true; var extensionNamespace = methodSymbol.IsExtensionMethod ? methodSymbol.ContainingNamespace.FullNameWithDot() + methodSymbol.ContainingType.FullName() : null; //null means it's not an extension method, non-null means it is string methodName; string typeParameters = null; ExpressionSyntax subExpressionOpt; if (expressionSymbol.Symbol is IEventSymbol) { methodName = "Invoke"; } else if (methodSymbol.MethodKind == MethodKind.DelegateInvoke) { methodName = null; } else { methodName = OverloadResolver.MethodName(methodSymbol); } if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface || Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol)) { /* methodName = * Regex.Replace(TypeProcessor.ConvertType(methodSymbol.ContainingType.OriginalDefinition) * .RemoveFromStartOfString(methodSymbol.ContainingNamespace + ".Namespace.") + "_" + * methodName, * @" ?!\(.*?\)", string.Empty);*/ if (methodSymbol.ContainingType.ContainingType != null) { methodName = methodName.RemoveFromStartOfString(methodSymbol.ContainingType.ContainingType.Name + "."); } } var interfaceMethods = methodSymbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(methodName)).ToArray(); ISymbol interfaceMethod = interfaceMethods.FirstOrDefault( o => methodSymbol.ContainingType.FindImplementationForInterfaceMember(o) == methodSymbol); // if (interfaceMethod == null) // { // //TODO: fix this for virtual method test 7, seems roslyn cannot deal with virtual // // overrides of interface methods ... so i'll provide a kludge // if (!method.Modifiers.Any(SyntaxKind.NewKeyword)) // interfaceMethod = interfaceMethods.FirstOrDefault(k => CompareMethods(k as IMethodSymbol, methodSymbol)); // } if (interfaceMethod != null) // && CompareMethods(interfaceMethod ,methodSymbol)) { { //This is an interface method //TO if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array) { writer.Write(""); } else { /* var typenameI = * Regex.Replace( * TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom, true), * @" ?!\(.*?\)", string.Empty); * //TODO: we should be able to get the original interface name, or just remove all generics from this * if (typenameI.Contains('.')) * typenameI = typenameI.SubstringAfterLast('.'); * writer.Write(typenameI + "_");*/ } } var containingType = interfaceMethod == null ? methodSymbol.ContainingType : interfaceMethod.ContainingType; bool isVirtualGeneric = methodSymbol.IsGenericMethod && (methodSymbol.IsVirtual || methodSymbol.ContainingType.TypeKind == TypeKind.Interface) && !containingType.IsAssignableFrom(Context.Instance.Type); // !(invocationExpression.Expression is BaseExpressionSyntax); if (isVirtualGeneric) { methodName = TypeProcessor.ConvertType(containingType, false, false, false).Replace(".", "_") + "_" + methodName; } if (methodSymbol.MethodKind == MethodKind.DelegateInvoke) { subExpressionOpt = invocationExpression.Expression; } else if (memberReferenceExpressionOpt != null) { if (memberReferenceExpressionOpt.Expression is PredefinedTypeSyntax) { subExpressionOpt = null; } else { subExpressionOpt = memberReferenceExpressionOpt.Expression; } } else { subExpressionOpt = null; } //When the code specifically names generic arguments, include them in the method name ... dmd needs help with inference, so we give it the types anyway if (methodSymbol.IsGenericMethod) { //return TryConvertType(named) + (named.TypeKind == TypeKind.Struct && o.ConstraintTypes.Any(k => k.TypeKind == //TypeKind.Interface) ? ".__Boxed_" : ""); var named = ((IMethodSymbol)symbol); typeParameters = "!(" + named.TypeArguments.Select(o => TypeProcessor.GetGenericParameterType(named.TypeParameters[named.TypeArguments.IndexOf(o)], o)).Aggregate((a, b) => a + ", " + b) + ")"; // typeParameters = "!( " + // string.Join(", ", // ((IMethodSymbol) symbol).TypeArguments.Select(r => TypeProcessor.ConvertType(r) )) + // " )"; } //Determine if it's an extension method called in a non-extension way. In this case, just pretend it's not an extension method if (extensionNamespace != null && subExpressionOpt != null && TypeProcessor.GetTypeInfo(subExpressionOpt).ConvertedType.ToString() == methodSymbol.ContainingNamespace.FullName() + "." + methodSymbol.ContainingType.FullName()) { extensionNamespace = null; } var memberType = memberReferenceExpressionOpt == null ? null : TypeProcessor.GetTypeInfo(memberReferenceExpressionOpt.Expression).Type; var isNullableEnum = memberType != null && (memberType.Name == "Nullable" && memberType.ContainingNamespace.FullName() == "System") && memberType.As <INamedTypeSymbol>().TypeArguments.Single().TypeKind == TypeKind.Enum; // if (isNullableEnum && methodSymbol.Name == "ToString") // { // extensionNamespace = null; //override Translations.xml for nullable enums. We want them to convert to the enum's ToString method // methodName = "toString"; // } //Invocation on basics should come from boxing the basic then calling on the boxed type, unless static var directInvocationOnBasics = methodSymbol.ContainingType.IsBasicType() && methodSymbol.IsStatic; //&& methodSymbol.ContainingType!=Context.Instance.Type; //If we are currently working on a basic type e.g. in corlib, don't alter the code //Extension methods in Dlang are straightforward, although this could lead to clashes without qualification string instanceName = null; if (extensionNamespace != null || directInvocationOnBasics) { if (extensionNamespace == null) { extensionNamespace = TypeProcessor.ConvertType(methodSymbol.ContainingType, true, false); // methodSymbol.ContainingNamespace.FullName() + "." + methodSymbol.ContainingType.Name; //memberType.ContainingNamespace.FullName() +"."+ memberType.Name; } if (!isVirtualGeneric) { writer.Write(extensionNamespace); if (methodName != null) { methodName = WriteIdentifierName.TransformIdentifier(methodName); // if (symbolInfo.Symbol.ContainingType != Context.Instance.Type) writer.Write("."); writer.Write(methodName); } } else { writer.Write(methodName); } WriteTypeParameters(writer, typeParameters, invocationExpression); writer.Write("("); if (subExpressionOpt != null) { firstParameter = false; Core.Write(writer, subExpressionOpt); } } else { if (memberReferenceExpressionOpt != null) { } if (subExpressionOpt != null) { if (!isVirtualGeneric) { WriteMemberAccessExpression.WriteMember(writer, subExpressionOpt); // if (!(subExpressionOpt is BaseExpressionSyntax)) // { // if (methodName != null && methodSymbol.IsStatic) // writer.Write("."); // else // { if (methodSymbol.MethodKind != MethodKind.DelegateInvoke) { writer.Write("."); } } else { instanceName = WriteMemberAccessExpression.WriteMemberToString(subExpressionOpt); } // } // } // writer.Write("."); } else if (methodSymbol.IsStatic && extensionNamespace == null) { if (methodSymbol.ContainingType != Context.Instance.Type) { var str = TypeProcessor.ConvertType(methodSymbol.ContainingType); if (str == "Array_T") { // Array is the only special case, otherwise generics have to be specialized to access static members str = "Array"; } writer.Write(str); // writer.Write(methodSymbol.ContainingNamespace.FullNameWithDot()); // writer.Write(WriteType.TypeName(methodSymbol.ContainingType)); writer.Write("."); } } if (methodSymbol.MethodKind != MethodKind.DelegateInvoke) { var declaringSyntaxReferences = methodSymbol.DeclaringSyntaxReferences.Select(j => j.GetSyntax()) .OfType <MethodDeclarationSyntax>(); var methodDeclarationSyntaxs = declaringSyntaxReferences as MethodDeclarationSyntax[] ?? declaringSyntaxReferences.ToArray(); var any = methodDeclarationSyntaxs.Any(); if (any && methodDeclarationSyntaxs.FirstOrDefault() .As <MethodDeclarationSyntax>() .Modifiers.Any(SyntaxKind.NewKeyword)) { //TODO: this means that new is not supported on external libraries // //why doesnt roslyn give me this information ? //methodName += "_"; //Not needed anymore :) } if (any && methodDeclarationSyntaxs.FirstOrDefault() .As <MethodDeclarationSyntax>() .Modifiers.Any(SyntaxKind.NewKeyword)) { // if (symbolInfo.Symbol.ContainingType != Context.Instance.Type) writer.Write(WriteIdentifierName.TransformIdentifier(methodSymbol.ContainingType.Name, methodSymbol.ContainingType) + "."); } methodName = WriteIdentifierName.TransformIdentifier(methodName); writer.Write(methodName); } WriteTypeParameters(writer, typeParameters, invocationExpression); writer.Write("("); } bool inParams = false; bool foundParamsArray = false; var arguments = invocationExpression.ArgumentList.Arguments; ITypeSymbol typeSymbol = null; bool isOverloaded = methodSymbol.ContainingType.GetMembers(methodSymbol.Name).OfType <IMethodSymbol>().Any(j => j.TypeParameters == methodSymbol.TypeParameters && ParameterMatchesWithRefOutIn(methodSymbol, j)); WriteArguments(writer, invocationExpression, arguments, firstParameter, inParams, methodSymbol, foundParamsArray, typeSymbol, isOverloaded, symbol, instanceName); }
public static void Go(OutputWriter writer, OperatorDeclarationSyntax method) { var methodSymbol = (IMethodSymbol)TypeProcessor.GetDeclaredSymbol(method); var actualMethodName = OverloadResolver.MethodName(methodSymbol); writer.Write("\n"); var returnType = ""; if (method.ReturnType.ToString() == "void") { returnType = ("void "); } else { returnType = TypeProcessor.ConvertType(method.ReturnType) + " "; // writer.Write(returnType); } var methodName = ""; if (BinaryOperators.ContainsKey(actualMethodName)) { methodName = "opBinary"; var typeSymbolParam0 = TypeProcessor.GetTypeInfo(method.ParameterList.Parameters[0].Type); var typeSymbolParent = (methodSymbol.ContainingType); if (typeSymbolParam0.Type != typeSymbolParent) { methodName += "Right"; } } if (UnaryOperators.ContainsKey(actualMethodName)) { methodName = "opUnary"; } if (EqualsOperators.ContainsKey(actualMethodName)) { methodName = "opEquals"; } if (CmpOperators.ContainsKey(actualMethodName)) { methodName = "opCmp"; } if (AssignOperators.ContainsKey(actualMethodName)) { methodName = "opAssign"; } if (AssignOpOperators.ContainsKey(actualMethodName)) { methodName = "opOpAssign"; // need to remove = from the name } var paramType = method.ParameterList.Parameters[0]; if (method.ParameterList.Parameters.Count == 2) { if (methodName.EndsWith("Right")) { paramType = method.ParameterList.Parameters[0]; } else { paramType = method.ParameterList.Parameters[1]; } } var token = method.OperatorToken.Text; var methodBody = ""; var temp = new TempWriter(); foreach (var statement in method.Body.Statements) { Core.Write(temp, statement); } TriviaProcessor.ProcessTrivias(temp, method.Body.DescendantTrivia()); methodBody = temp.ToString(); if (methodName == "opOpAssign") { token = token.Substring(0, 1); } //We are going to have to rewrite this bit later ... for now all overloads are called directly /* if (methodName == "opBinary") * { * * writer.WriteLine("public final " + returnType + " " + methodName + * String.Format( * " (string _op) ({0} other)\r\n\tif(_op==\"{2}\")\r\n\t{{ \r\n\t\treturn {1}(this,other); \r\n\t}}\r\n\r\n", * TypeProcessor.ConvertType(paramType.Type), actualMethodName, token)); * * //Add Assignment operator if it doesn't exist * if (!methodSymbol.ContainingType.GetMembers(AssignOpOperators.FirstOrDefault(k => k.Value == token + "=").Key).Any()) * { * writer.WriteLine("public final " + returnType + " opOpAssign" + * String.Format( * " (string _op) ({0} other)\r\n\tif(_op==\"{2}\")\r\n\t{{ \r\n\t\treturn {1}(this,other); \r\n\t}}\r\n\r\n", * TypeProcessor.ConvertType(paramType.Type), actualMethodName, token)); * } * } * else if (methodName == "opUnary")//TODO unary operators are mostly going to be direct methodCalls * { * * writer.WriteLine("public final " + returnType + " " + methodName + * String.Format( * " (string _op) ()\r\n\tif(_op==\"{2}\")\r\n\t{{ \r\n\t\treturn {1}(this); \r\n\t}}\r\n\r\n", * TypeProcessor.ConvertType(paramType.Type), actualMethodName, token)); * // writer.WriteLine ("public final ref " + returnType + " " + methodName + * // String.Format ( * // " (string _op) ()\r\n\tif(_op==\"{2}\")\r\n\t{{ \r\n\t\t{3}\r\n\t}}\r\n\r\n", * //TypeProcessor.ConvertType (paramType.Type), actualMethodName, token, methodBody.Replace(method.ParameterList.Parameters[0].Identifier.ValueText,"this"))); * } * else * { * writer.WriteLine("public final " + returnType + " " + methodName + * String.Format( * " (string _op) ({0} other)\r\n\tif(_op==\"{2}\")\r\n\t{{ \r\n\t\treturn {1}(this); \r\n\t}}\r\n\r\n", * TypeProcessor.ConvertType(paramType.Type), actualMethodName, token)); * }*/ var @params = method.ParameterList.Parameters; writer.WriteLine("public static " + returnType + " " + actualMethodName + WriteMethod.GetParameterListAsString(method.ParameterList.Parameters)); writer.OpenBrace(); if (method.Body != null) { foreach (var statement in method.Body.Statements) { Core.Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, method.Body.DescendantTrivia()); } writer.CloseBrace(); }
public static void Go(OutputWriter writer, OperatorDeclarationSyntax method) { var methodSymbol = (IMethodSymbol)TypeProcessor.GetDeclaredSymbol(method); var ActualMethodName = OverloadResolver.MethodName(methodSymbol); // var methodType = Program.GetModel(method).GetTypeInfo(method); writer.Write("\n"); var isInterface = method.Parent is InterfaceDeclarationSyntax; if (method.Modifiers.Any(SyntaxKind.PublicKeyword) || method.Modifiers.Any(SyntaxKind.InternalKeyword) || method.Modifiers.Any(SyntaxKind.ProtectedKeyword) || method.Modifiers.Any(SyntaxKind.AbstractKeyword) || isInterface) { writer.Write("public "); } var returnType = ""; if (method.ReturnType.ToString() == "void") { writer.Write("void "); } else { // var typeSymbol = TypeProcessor.GetTypeInfo(method.ReturnType).Type; // var isPtr = typeSymbol != null && (typeSymbol.IsValueType || typeSymbol.TypeKind == TypeKind.TypeParameter) ? "" : ""; // var typeString = TypeProcessor.ConvertType(method.ReturnType) + isPtr + " "; // writer.Write(typeString); // writer.HeaderWriter.Write(typeString); // var isPtr = typeSymbol != null && (!typeSymbol.IsValueType || typeSymbol.TypeKind == TypeKind.TypeParameter); returnType = TypeProcessor.ConvertType(method.ReturnType) + " "; writer.Write(returnType); } var methodName = ""; if (binaryOperators.Contains(method.OperatorToken.ValueText)) { methodName = "opBinary"; var typeSymbolParam0 = TypeProcessor.GetTypeInfo(method.ParameterList.Parameters[0].Type); var typeSymbolParent = (methodSymbol.ContainingType); if (typeSymbolParam0.Type != typeSymbolParent) { methodName += "Right"; } } if (unaryOperators.Contains(method.OperatorToken.ValueText)) { methodName = "opUnary"; } if (equalsOperators.Contains(method.OperatorToken.ValueText)) { methodName = "opEquals"; } if (cmpOperators.Contains(method.OperatorToken.ValueText)) { methodName = "opCmp"; } if (assignOperators.Contains(method.OperatorToken.ValueText)) { methodName = "opAssign"; } if (assignOpOperators.Contains(method.OperatorToken.ValueText)) { methodName = "opOpAssign"; // need to remove = from the name } //method.ParameterList.Parameters[0]; var paramType = method.ParameterList.Parameters[0]; if (method.ParameterList.Parameters.Count == 2) { if (methodName.EndsWith("Right")) { paramType = method.ParameterList.Parameters[0]; } else { paramType = method.ParameterList.Parameters[1]; } } var token = method.OperatorToken.ValueText; if (methodName == "opOpAssign") { token = token.Substring(0, 1); } writer.Write(methodName + String.Format( " (string _op) ({0} other)\r\nif(_op==\"{2}\")\r\n{{ \r\nreturn {1}(this,other); \r\n}}\r\n", TypeProcessor.ConvertType(paramType.Type), ActualMethodName, token)); writer.Write("\r\n\r\npublic static " + returnType + " " + ActualMethodName); WriteParameterList(writer, method.ParameterList); writer.WriteLine(); writer.OpenBrace(); writer.WriteLine(); if (method.Body != null) { foreach (var statement in method.Body.Statements) { Core.Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, method.Body.DescendantTrivia()); } writer.WriteLine(); writer.CloseBrace(); writer.WriteLine(); }
public static void WriteInstanceConstructor(OutputWriter writer, ConstructorDeclarationSyntax method) { var methodSymbol = (IMethodSymbol)TypeProcessor.GetDeclaredSymbol(method); var methodName = OverloadResolver.MethodName(methodSymbol); // var methodType = Program.GetModel(method).GetTypeInfo(method); //TODO: Improve partial class / method support 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 <ConstructorDeclarationSyntax>() .Except(method).Any(o => o.Identifier.ValueText == method.Identifier.ValueText)) { return; } } // if (method.Identifier.ValueText == "GetEnumerator") // return; //TODO: Support enumerator methods writer.WriteLine(); // writer.WriteIndent(); var accessmodifiers = ""; var isInterface = method.Parent is InterfaceDeclarationSyntax; if (method.Modifiers.Any(SyntaxKind.PublicKeyword) || method.Modifiers.Any(SyntaxKind.InternalKeyword) || method.Modifiers.Any(SyntaxKind.ProtectedKeyword) || method.Modifiers.Any(SyntaxKind.AbstractKeyword) || isInterface) { accessmodifiers += ("public "); } if (method.Modifiers.Any(SyntaxKind.PrivateKeyword)) { accessmodifiers += ("private "); } if (ShouldUseOverrideKeyword(method, methodSymbol)) { accessmodifiers += ("override "); } //D does not use the virtual keyword // if (method.Modifiers.Any(SyntaxKind.VirtualKeyword) || isInterface) // writer.Write("virtual "); //Need to improve performance by labling non virtual methods with "final" ... but we have to check the original definition of the method if (method.Modifiers.Any(SyntaxKind.StaticKeyword)) { accessmodifiers += ("static "); } if (isInterface) { // writer.IsInterface = true; } //Constructors in d dont have return types // writer.Write("void "); // writer.HeaderWriter.Write("void "); // writer.Write("this"); // writer.Write("("); // var firstParam = true; // foreach (var parameter in method.ParameterList.Parameters) // { // bool isRef = parameter.Modifiers.Any(SyntaxKind.OutKeyword) || // parameter.Modifiers.Any(SyntaxKind.RefKeyword); // // if (firstParam) // firstParam = false; // else // { // writer.Write(", "); // } // // // var localSymbol = TypeProcessor.GetTypeInfo(parameter.Type); // var ptr = (localSymbol.Type != null && !localSymbol.Type.IsValueType) ? "" : ""; // // if (!isRef) // { // var s = TypeProcessor.ConvertType(parameter.Type) + " " + ptr; // writer.Write(s); // } // else // { // // // // var s = " ref " + TypeProcessor.ConvertType(parameter.Type) + " "; // Refs in D are simple // // writer.Write(s); // // Program.RefOutSymbols.TryAdd(TypeProcessor.GetDeclaredSymbol(parameter), null); // } // // writer.Write(WriteIdentifierName.TransformIdentifier(parameter.Identifier.ValueText)); // // if (parameter.Default != null) // { // writer.Write(" = "); // Core.Write(writer, parameter.Default.Value); // } // } // // writer.Write(")"); writer.WriteLine(accessmodifiers + "this" + WriteMethod.GetParameterListAsString(method.ParameterList)); if (isInterface || method.Modifiers.Any(SyntaxKind.AbstractKeyword)) { writer.Write(" = 0;\r\n"); return; } //if (!returnsVoid) // writer.Write(" ="); // writer.Write("\r\n"); writer.OpenBrace(); if (method.Initializer != null) { //writer.Write(":"); Core.Write(writer, method.Initializer); writer.Write(";"); writer.WriteLine(); //";\r\n"); } if (method.Body != null) { foreach (var statement in method.Body.Statements) { Core.Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, method.Body.DescendantTrivia()); } writer.CloseBrace(); }
private static void ProcessExpression(OutputWriter writer, SyntaxToken operatorToken, CSharpSyntaxNode rightExpression, CSharpSyntaxNode leftExpression) { TypeInfo leftExpressionType = TypeProcessor.GetTypeInfo(leftExpression ?? rightExpression); var rightExpressionType = TypeProcessor.GetTypeInfo(rightExpression); var boxLeft = leftExpressionType.Type != null && (leftExpressionType.Type != leftExpressionType.ConvertedType) && ((leftExpressionType.Type.IsValueType || leftExpressionType.Type.TypeKind == TypeKind.TypeParameter) && (leftExpressionType.ConvertedType.IsReferenceType)); var boxRight = (rightExpressionType.ConvertedType != null && (rightExpressionType.Type != null && ((rightExpressionType.Type.IsValueType || rightExpressionType.Type.TypeKind == TypeKind.TypeParameter) && (rightExpressionType.ConvertedType.IsReferenceType)))) || (rightExpressionType.Type != null && rightExpressionType.Type.IsValueType && leftExpressionType.Type != null && leftExpressionType.Type.TypeKind == TypeKind.Error); //Fix for yield ... why does it give errortypes ? var unboxRight = rightExpressionType.ConvertedType != null && (rightExpressionType.Type != null && (rightExpressionType.Type.IsReferenceType && (rightExpressionType.ConvertedType.IsValueType))); var rightnull = rightExpression != null && rightExpression.ToFullString().Trim() == "null"; var leftnull = leftExpression != null && leftExpression.ToFullString().Trim() == "null"; var nullAssignment = (rightnull || leftnull); var val = WriteOperatorDeclaration.AllBinaryOperators.FirstOrDefault(k => k.Value == operatorToken.Text); //Matching Binary Operator Overload if (!String.IsNullOrEmpty(val.Value)) { //Try Left IEnumerable <ISymbol> members = new List <ISymbol>(); if (leftExpressionType.Type != null) { members = leftExpressionType.Type.GetMembers(val.Key); } if (rightExpressionType.Type != null) { members = members. Union(rightExpressionType.Type.GetMembers(val.Key)); } var leftExpressionString = Core.WriteString(leftExpression); if (members != null && members.Any()) { if (!(leftExpressionType.Type.IsPrimitive() && rightExpressionType.Type.IsPrimitive())) { var correctOverload = members.OfType <IMethodSymbol>() .FirstOrDefault( u => u.Parameters[0].Type == leftExpressionType.Type && u.Parameters[1].Type == rightExpressionType.Type); if (correctOverload != null) { var name = WriteIdentifierName.TransformIdentifier(OverloadResolver.MethodName(correctOverload)); writer.Write(TypeProcessor.ConvertType(correctOverload.ContainingType) + "." + name + "(" + leftExpressionString + "," + Core.WriteString(rightExpression) + ")"); return; } } } else { if (WriteOperatorDeclaration.AssignOpOperators.ContainsKey(val.Key)) { var methodName = WriteOperatorDeclaration.AllBinaryOperators.FirstOrDefault( k => k.Value == val.Value.Substring(0, 1)); // emulate c# facility to use the lower op ... //Try Left members = null; if (leftExpressionType.Type != null) { members = leftExpressionType.Type.GetMembers(methodName.Key); } if (rightExpressionType.Type != null) { members = members. Union(rightExpressionType.Type.GetMembers(methodName.Key)); } if (members != null && members.Any()) { if (!(leftExpressionType.Type.IsPrimitive() && rightExpressionType.Type.IsPrimitive())) { var correctOverload = members.OfType <IMethodSymbol>() .FirstOrDefault( u => u.Parameters[0].Type == leftExpressionType.Type && u.Parameters[1].Type == rightExpressionType.Type); if (correctOverload != null) { var name = WriteIdentifierName.TransformIdentifier( OverloadResolver.MethodName(correctOverload)); writer.Write(leftExpressionString + " = " + TypeProcessor.ConvertType(correctOverload.ContainingType) + "." + name + "(" + leftExpressionString + "," + Core.WriteString(rightExpression) + ")"); return; } } } } } } //Property calls will be fixed in a preprocessor step ... i.e. just call them if (nullAssignment) { if (rightnull) { switch (operatorToken.CSharpKind()) { case SyntaxKind.EqualsEqualsToken: writer.Write(""); break; case SyntaxKind.NotEqualsExpression: case SyntaxKind.ExclamationEqualsToken: writer.Write("!"); break; default: writer.Write(operatorToken.ToString()); break; } writer.Write("__IsNull("); Core.Write(writer, leftExpression); writer.Write(")"); return; } if (leftnull) { // writer.Write("null"); // // switch (operatorToken.CSharpKind()) // { // case SyntaxKind.EqualsEqualsToken: // writer.Write(" is "); // break; // case SyntaxKind.NotEqualsExpression: // case SyntaxKind.ExclamationEqualsToken: // writer.Write(" !is "); // break; // default: // writer.Write(operatorToken.ToString()); // break; // } // // Core.Write(writer, rightExpression); // // return; switch (operatorToken.CSharpKind()) { case SyntaxKind.EqualsEqualsToken: writer.Write(""); break; case SyntaxKind.NotEqualsExpression: case SyntaxKind.ExclamationEqualsToken: writer.Write("!"); break; default: writer.Write(operatorToken.ToString()); break; } writer.Write("__IsNull("); Core.Write(writer, rightExpression); writer.Write(")"); return; } } //Do we have an implicit converter, if so, use it if (leftExpressionType.Type != rightExpressionType.Type && rightExpressionType.Type != null) { bool useType = true; //We should start with exact converters and then move to more generic convertors i.e. base class or integers which are implicitly convertible var correctConverter = leftExpressionType.Type.GetImplicitCoversionOp(leftExpressionType.Type, rightExpressionType.Type, true); if (correctConverter == null) { useType = false; correctConverter = rightExpressionType.Type.GetImplicitCoversionOp(leftExpressionType.Type, rightExpressionType.Type, true); } if (correctConverter != null) { Core.Write(writer, leftExpression); writer.Write(operatorToken.ToString()); if (useType) { writer.Write(TypeProcessor.ConvertType(leftExpressionType.Type) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } else { writer.Write(TypeProcessor.ConvertType(rightExpressionType.Type) + "." + "op_Implicit_" + TypeProcessor.ConvertType(correctConverter.ReturnType, false, true, false).Replace(".", "_")); } writer.Write("("); Core.Write(writer, rightExpression); writer.Write(")"); return; } } if (operatorToken.CSharpKind() == SyntaxKind.PlusEqualsToken || operatorToken.CSharpKind() == SyntaxKind.MinusEqualsToken) { var isname = rightExpression is NameSyntax; var nameexpression = rightExpression as NameSyntax; var ismemberexpression = rightExpression is MemberAccessExpressionSyntax || (isname && TypeProcessor.GetSymbolInfo(rightExpression as NameSyntax).Symbol.Kind == SymbolKind.Method); var isdelegateassignment = rightExpressionType.ConvertedType != null && (ismemberexpression && rightExpressionType.ConvertedType .TypeKind == TypeKind.Delegate); var memberaccessexpression = rightExpression as MemberAccessExpressionSyntax; var isstaticdelegate = isdelegateassignment && ((memberaccessexpression != null && TypeProcessor.GetSymbolInfo(memberaccessexpression).Symbol.IsStatic) || (isname && TypeProcessor.GetSymbolInfo(nameexpression).Symbol.IsStatic)); if (isdelegateassignment) { Core.Write(writer, leftExpression); writer.Write(operatorToken.ToString()); var typeString = TypeProcessor.ConvertType(rightExpressionType.ConvertedType); if (rightExpressionType.ConvertedType.TypeKind == TypeKind.TypeParameter) { writer.Write(" __TypeNew!(" + typeString + ")("); } else { writer.Write("new " + typeString + "("); } var isStatic = isstaticdelegate; // if (isStatic) // writer.Write("__ToDelegate("); MemberUtilities.WriteMethodPointer(writer, rightExpression); // if (isStatic) // writer.Write(")"); writer.Write(")"); return; } } if (leftExpressionType.Type == null || (rightExpressionType.Type == null && rightExpression != null)) { // seems we have a null here obj==null or null==obj if ((rightExpressionType.Type != null && rightExpressionType.Type.IsValueType) || (leftExpressionType.Type != null && leftExpressionType.Type.IsValueType)) { writer.Write("/*value type cannot be null*/"); Core.Write(writer, leftExpression); switch (operatorToken.CSharpKind()) { case SyntaxKind.EqualsEqualsToken: writer.Write("!="); break; case SyntaxKind.NotEqualsExpression: writer.Write("=="); break; default: writer.Write(operatorToken.ToString()); break; } Core.Write(writer, rightExpression); } else { Core.Write(writer, leftExpression); if (operatorToken.CSharpKind() == SyntaxKind.EqualsEqualsToken) { writer.Write(" is "); } else if (operatorToken.CSharpKind() == SyntaxKind.ExclamationEqualsToken) { writer.Write(" !is "); } else { writer.Write(operatorToken.ToString()); } if (rightExpression != null) { Core.Write(writer, rightExpression); } } } else { writer.Write(boxLeft ? "BOX!(" + TypeProcessor.ConvertType(leftExpressionType.Type) + ")(" : ""); Core.Write(writer, leftExpression); writer.Write(boxLeft ? ")" : ""); writer.Write(operatorToken.ToString()); if (rightExpression != null) { writer.Write(unboxRight ? "UNBOX!(" + TypeProcessor.ConvertType(rightExpressionType.ConvertedType) + ")(" : ""); writer.Write(boxRight ? "BOX!(" + TypeProcessor.ConvertType(rightExpressionType.Type) + ")(" : ""); Core.Write(writer, rightExpression); writer.Write(boxRight ? ")" : ""); writer.Write(unboxRight ? ")" : ""); } } }
public static string GetMethodName(MemberDeclarationSyntax member, ref bool isInterface, out ITypeSymbol interfaceImplemented, out ISymbol[] proxies) { interfaceImplemented = null; proxies = null; var methodSymbol = TypeProcessor.GetDeclaredSymbol(member); var name = WriteIdentifierName.TransformIdentifier(OverloadResolver.MethodName(methodSymbol)); if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface) { isInterface = true; interfaceImplemented = methodSymbol.ContainingType; } var isinterfacemethod = Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol); if (!isinterfacemethod && methodSymbol.IsOverride) { isinterfacemethod = Equals(methodSymbol.ContainingType.BaseType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol); } if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface || (isinterfacemethod && methodSymbol.IsOverride)) { /* name = Regex.Replace( * TypeProcessor.ConvertType(methodSymbol.ContainingType.ConstructedFrom) + "_" + name, * @" ?!\(.*?\)", String.Empty);*/ interfaceImplemented = methodSymbol.ContainingType.ConstructedFrom; if (methodSymbol.ContainingType.ContainingType != null) { name = name.RemoveFromStartOfString(methodSymbol.ContainingType.ContainingType.Name + "."); } } if (name.Contains(".")) // Explicit Interface method { // name = name.SubstringAfterLast('.'); name = name.Replace('.', '_'); } var name1 = name; IEnumerable <ISymbol> interfaceMethods = null; if (methodSymbol.IsOverride && (interfaceMethods == null || !interfaceMethods.Any())) { interfaceMethods = methodSymbol.ContainingType.BaseType.AllInterfaces.SelectMany( u => u.GetMembers(name1)); if ((interfaceMethods == null || !interfaceMethods.Any())) { interfaceMethods = interfaceMethods.Where( o => Equals(methodSymbol.ContainingType.BaseType.FindImplementationForInterfaceMember(o), methodSymbol)); } } else { interfaceMethods = methodSymbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(name1)); interfaceMethods = interfaceMethods.Where( o => Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(o), methodSymbol)); } var enumerable = interfaceMethods as ISymbol[] ?? interfaceMethods.ToArray(); var interfaceMethod = enumerable.FirstOrDefault(); if (interfaceMethods.Count() > 1) { proxies = interfaceMethods.ToArray(); } if (interfaceMethod != null) { //TODO: fix this for virtual method test 7, seems roslyn cannot deal with virtual // overrides of interface methods ... so i'll provide a kludge // if (!member.GetModifiers().Any(SyntaxKind.NewKeyword) && methodSymbol is IMethodSymbol) // This is not neccessary for properties // { // interfaceMethod = // enumerable.FirstOrDefault(k => CompareMethods(k as IMethodSymbol, (IMethodSymbol) methodSymbol)); // } } if (interfaceMethod != null) { //This is an interface method/property //TO if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array) { name += (""); } else { /* var typenameI = * Regex.Replace(TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom), * @" ?!\(.*?\)", String.Empty);*/ //TODO: we should be able to get the original interface name, or just remove all generics from this interfaceImplemented = interfaceMethod.ContainingType;//.ConstructedFrom; /* if (typenameI.Contains('.')) * typenameI = typenameI.SubstringAfterLast('.'); * name = (typenameI + "_") + name;*/ } } // if (member.GetModifiers().Any(SyntaxKind.NewKeyword) && methodSymbol.OriginalDefinition.ContainingType.TypeKind != TypeKind.Interface) //Take care of new // name += "_"; if (methodSymbol.IsNew()) { // name += "_"; interfaceImplemented = methodSymbol.OriginalDefinition.ContainingType; } GetExplicitInterface(ref interfaceImplemented, methodSymbol); // if (interfaceMethods.Count() >= 1 && interfaceMethod!=null) // proxies = interfaceMethods.ToArray(); return(name); }
public static void Go(OutputWriter writer, InvocationExpressionSyntax invocationExpression) { var symbolInfo = TypeProcessor.GetSymbolInfo(invocationExpression); var expressionSymbol = TypeProcessor.GetSymbolInfo(invocationExpression.Expression); var symbol = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault(); // Resolution error var methodSymbol = symbol.OriginalDefinition.As <IMethodSymbol>().UnReduce(); var memberReferenceExpressionOpt = invocationExpression.Expression as MemberAccessExpressionSyntax; var firstParameter = true; var extensionNamespace = methodSymbol.IsExtensionMethod ? methodSymbol.ContainingNamespace.FullNameWithDot() + methodSymbol.ContainingType.FullName() : null; //null means it's not an extension method, non-null means it is string methodName; string typeParameters = null; ExpressionSyntax subExpressionOpt; if (methodSymbol.ContainingType.FullName() == "Enum") { if (methodSymbol.Name == "Parse") { WriteEnumParse(writer, invocationExpression); return; } if (methodSymbol.Name == "GetValues") { WriteEnumGetValues(writer, invocationExpression); return; } } if (expressionSymbol.Symbol is IEventSymbol) { methodName = "Invoke"; //Would need to append the number of arguments to this to support events. However, events are not currently supported } // else if (memberReferenceExpressionOpt != null && memberReferenceExpressionOpt.Expression is PredefinedTypeSyntax) // { // switch (methodSymbol.Name) // { // case "Parse": // Core.Write(writer, invocationExpression.ArgumentList.Arguments.Single().Expression); // // writer.Write(".to"); // writer.Write(TypeProcessor.ConvertType(methodSymbol.ReturnType)); // // return; // case "TryParse": // methodName = "TryParse" + TypeProcessor.ConvertType(methodSymbol.Parameters[1].Type); // extensionNamespace = "SharpNative"; // break; // default: // methodName = methodSymbol.Name; // extensionNamespace = "SharpNative"; // break; // } // } else if (methodSymbol.MethodKind == MethodKind.DelegateInvoke) { methodName = null; } else { methodName = OverloadResolver.MethodName(methodSymbol); } if (methodSymbol.MethodKind == MethodKind.DelegateInvoke) { subExpressionOpt = invocationExpression.Expression; } else if (memberReferenceExpressionOpt != null) { if (memberReferenceExpressionOpt.Expression is PredefinedTypeSyntax) { subExpressionOpt = null; } else { subExpressionOpt = memberReferenceExpressionOpt.Expression; } } else { subExpressionOpt = null; } //When the code specifically names generic arguments, include them in the method name ... dlang needs help with inference, so we give it the types anyway if (methodSymbol.IsGenericMethod) { // var genNameExpression = invocationExpression.Expression as GenericNameSyntax; // if (genNameExpression == null && memberReferenceExpressionOpt != null) // genNameExpression = memberReferenceExpressionOpt.Name as GenericNameSyntax; // if (genNameExpression != null && genNameExpression.TypeArgumentList.Arguments.Count > 0) typeParameters = "!( " + string.Join(", ", (symbol as IMethodSymbol).TypeArguments.Select(r => TypeProcessor.ConvertType(r))) + " )"; } //Determine if it's an extension method called in a non-extension way. In this case, just pretend it's not an extension method if (extensionNamespace != null && subExpressionOpt != null && TypeProcessor.GetTypeInfo(subExpressionOpt).ConvertedType.ToString() == methodSymbol.ContainingNamespace + "." + methodSymbol.ContainingType.FullName()) { extensionNamespace = null; } var memberType = memberReferenceExpressionOpt == null ? null : TypeProcessor.GetTypeInfo(memberReferenceExpressionOpt.Expression).Type; var isNullableEnum = memberType != null && (memberType.Name == "Nullable" && memberType.ContainingNamespace.FullName() == "System") && memberType.As <INamedTypeSymbol>().TypeArguments.Single().TypeKind == TypeKind.Enum; // if (isNullableEnum && methodSymbol.Name == "ToString") // { // extensionNamespace = null; //override Translations.xml for nullable enums. We want them to convert to the enum's ToString method // methodName = "toString"; // } var directInvocationOnBasics = methodSymbol.ContainingType.IsBasicType(); //Extension methods in Dlang are straightforward, although this could lead to clashes without qualification if (extensionNamespace != null || directInvocationOnBasics) { if (extensionNamespace == null) { extensionNamespace = memberType.ContainingNamespace.FullName() + "." + memberType.Name; //memberType.ContainingNamespace.FullName() +"."+ memberType.Name; } writer.Write(extensionNamespace); if (methodName != null) { writer.Write("."); writer.Write(methodName); } WriteTypeParameters(writer, typeParameters, invocationExpression); writer.Write("("); if (subExpressionOpt != null) { firstParameter = false; Core.Write(writer, subExpressionOpt); } } else { if (memberReferenceExpressionOpt != null) { //Check against lowercase toString since it gets replaced with the lowered version before we get here if (methodName == "toString") { if (memberType.TypeKind == TypeKind.Enum || isNullableEnum) { var enumType = memberType.TypeKind == TypeKind.Enum ? memberType : memberType.As <INamedTypeSymbol>().TypeArguments.Single(); //calling ToString() on an enum forwards to our enum's special ToString method writer.Write(enumType.ContainingNamespace.FullNameWithDot()); writer.Write(WriteType.TypeName((INamedTypeSymbol)enumType)); writer.Write(".ToString("); Core.Write(writer, memberReferenceExpressionOpt.Expression); writer.Write(")"); if (invocationExpression.ArgumentList.Arguments.Count > 0) { throw new Exception( "Enum's ToString detected with parameters. These are not supported " + Utility.Descriptor(invocationExpression)); } return; } if (memberType.SpecialType == SpecialType.System_Byte) { //Calling ToString on a byte needs to take special care since it's signed in the JVM writer.Write("System.SharpNative.ByteToString("); Core.Write(writer, memberReferenceExpressionOpt.Expression); writer.Write(")"); if (invocationExpression.ArgumentList.Arguments.Count > 0) { throw new Exception( "Byte's ToString detected with parameters. These are not supported " + Utility.Descriptor(invocationExpression)); } return; } } } if (subExpressionOpt != null) { WriteMemberAccessExpression.WriteMember(writer, subExpressionOpt); // if (!(subExpressionOpt is BaseExpressionSyntax)) // { // if (methodName != null && methodSymbol.IsStatic) // writer.Write("."); // else // { if (methodSymbol.MethodKind != MethodKind.DelegateInvoke) { writer.Write("."); } // } // } // writer.Write("."); } else if (methodSymbol.IsStatic && extensionNamespace == null) { var str = TypeProcessor.ConvertType(methodSymbol.ContainingType); if (str == "Array_T") { // Array is the only special case, otherwise generics have to be specialized to access static members str = "Array"; } writer.Write(str); // writer.Write(methodSymbol.ContainingNamespace.FullNameWithDot()); // writer.Write(WriteType.TypeName(methodSymbol.ContainingType)); writer.Write("."); } if (methodSymbol.MethodKind != MethodKind.DelegateInvoke) { var declaringSyntaxReferences = methodSymbol.DeclaringSyntaxReferences.Select(j => j.GetSyntax()) .OfType <MethodDeclarationSyntax>(); var any = declaringSyntaxReferences.Any(); if (any && declaringSyntaxReferences.FirstOrDefault() .As <MethodDeclarationSyntax>() .Modifiers.Any(SyntaxKind.NewKeyword)) { //TODO: this means that new is not supported on external libraries // //why doesnt roslyn give me this information ? methodName += "_"; } if (any && declaringSyntaxReferences.FirstOrDefault() .As <MethodDeclarationSyntax>() .Modifiers.Any(SyntaxKind.NewKeyword)) { writer.Write(TypeProcessor.ConvertType(methodSymbol.ContainingType) + "."); } //TODO: fix this for abstract too or whatever other combination //TODO: create a better fix fot this // ISymbol interfaceMethod = // methodSymbol.ContainingType.AllInterfaces.SelectMany ( // u => // u.GetMembers (methodName) // .Where ( // o => // methodSymbol.ContainingType.FindImplementationForInterfaceMember (o) == // methodSymbol)).FirstOrDefault (); /* if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface || * Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol)) * * if ((interfaceMethod != null /*&& interfaceMethod == methodSymbol || methodSymbol.ContainingType.TypeKind == TypeKind.Interface) * { * //This is an interface method //TO * * var typenameM = Regex.Replace (TypeProcessor.ConvertType (methodSymbol.ContainingType), @" ?!\(.*?\)", string.Empty); * if (typenameM.Contains ('.')) * typenameM = typenameM.SubstringAfterLast ('.'); * if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array) * writer.Write (""); * else if (interfaceMethod != null) * { * var typenameI = Regex.Replace (TypeProcessor.ConvertType (interfaceMethod.ContainingType), @" ?!\(.*?\)", string.Empty); * if (typenameI.Contains ('.')) * typenameI = typenameI.SubstringAfterLast ('.'); * writer.Write (typenameI + "_"); * } * else // this is the interface itself * writer.Write (typenameM + "_"); * * }*/ if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface || Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol)) { methodName = Regex.Replace( TypeProcessor.ConvertType(methodSymbol.ContainingType.OriginalDefinition) .RemoveFromStartOfString(methodSymbol.ContainingNamespace + ".Namespace.") + "_" + methodName, @" ?!\(.*?\)", string.Empty); } var interfaceMethods = methodSymbol.ContainingType.AllInterfaces.SelectMany( u => u.GetMembers(methodName)).ToArray(); ISymbol interfaceMethod = interfaceMethods.FirstOrDefault( o => methodSymbol.ContainingType.FindImplementationForInterfaceMember(o) == methodSymbol); // if (interfaceMethod == null) // { // //TODO: fix this for virtual method test 7, seems roslyn cannot deal with virtual // // overrides of interface methods ... so i'll provide a kludge // if (!method.Modifiers.Any(SyntaxKind.NewKeyword)) // interfaceMethod = interfaceMethods.FirstOrDefault(k => CompareMethods(k as IMethodSymbol, methodSymbol)); // } if (interfaceMethod != null) // && CompareMethods(interfaceMethod ,methodSymbol)) { { //This is an interface method //TO if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array) { writer.Write(""); } else { var typenameI = Regex.Replace( TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom, true), @" ?!\(.*?\)", string.Empty); //TODO: we should be able to get the original interface name, or just remove all generics from this if (typenameI.Contains('.')) { typenameI = typenameI.SubstringAfterLast('.'); } writer.Write(typenameI + "_"); } } // var acc = methodSymbol.DeclaredAccessibility; // if (methodSymbol.MethodKind == MethodKind.ExplicitInterfaceImplementation) // { // var implementations = methodSymbol.ExplicitInterfaceImplementations[0]; // if (implementations != null) // { // // explicitHeaderNAme = implementations.Name; // methodName = TypeProcessor.ConvertType(implementations.ReceiverType) + "_" +implementations.Name; //Explicit fix ? // // // writer.Write(methodSymbol.ContainingType + "." + methodName); // //Looks like internal classes are not handled properly here ... // } // } writer.Write(methodName); } WriteTypeParameters(writer, typeParameters, invocationExpression); writer.Write("("); } bool inParams = false; bool foundParamsArray = false; var arguments = invocationExpression.ArgumentList.Arguments; foreach (var arg in arguments.Select(o => new TransformedArgument(o))) { if (firstParameter) { firstParameter = false; } else { writer.Write(", "); } var argumentType = TypeProcessor.GetTypeInfo(arg.ArgumentOpt.Expression); // if (!inParams && IsParamsArgument (invocationExpression, arg.ArgumentOpt, methodSymbol)) // { // foundParamsArray = true; // // if (!TypeProcessor.ConvertType (TypeProcessor.GetTypeInfo (arg.ArgumentOpt.Expression).Type).StartsWith ("System.Array<")) // { // inParams = true; // writer.Write ("Array_T!("); // } // } //Not needed for dlang // if (arg != null // && arg.ArgumentOpt.RefOrOutKeyword.RawKind != (decimal) SyntaxKind.None // && TypeProcessor.GetSymbolInfo(arg.ArgumentOpt.Expression).Symbol is IFieldSymbol) // { // // } // throw new Exception("ref/out cannot reference fields, only local variables. Consider using ref/out on a local variable and then assigning it into the field. " + Utility.Descriptor(invocationExpression)); // if (argumentType.Type == null) { // if (argumentType.ConvertedType == null) // writer.Write ("null"); // else // writer.Write ("(cast("+TypeProcessor.ConvertType(argumentType.ConvertedType)+") null)"); // } // // else if (argumentType.Type.IsValueType && !argumentType.ConvertedType.IsValueType) // { // //Box // writer.Write("BOX!("+TypeProcessor.ConvertType(argumentType.Type) +")("); // //When passing an argument by ref or out, leave off the .Value suffix // if (arg != null && arg.ArgumentOpt.RefOrOutKeyword.RawKind != (decimal)SyntaxKind.None) // WriteIdentifierName.Go(writer, arg.ArgumentOpt.Expression.As<IdentifierNameSyntax>(), true); // else // arg.Write(writer); // // writer.Write(")"); // } // else if (!argumentType.Type.IsValueType && argumentType.ConvertedType.IsValueType) // { // //UnBox // writer.Write("cast(" + TypeProcessor.ConvertType(argumentType.Type) + ")("); // if (arg != null && arg.ArgumentOpt.RefOrOutKeyword.RawKind != (decimal)SyntaxKind.None) // WriteIdentifierName.Go(writer, arg.ArgumentOpt.Expression.As<IdentifierNameSyntax>(), true); // else // arg.Write(writer); // writer.Write(")"); // } // else // { // if (arg != null && arg.ArgumentOpt.RefOrOutKeyword.RawKind != (decimal)SyntaxKind.None) // WriteIdentifierName.Go(writer, arg.ArgumentOpt.Expression.As<IdentifierNameSyntax>(), true); // else // arg.Write(writer); // } ProcessArgument(writer, arg.ArgumentOpt); } // if (inParams) // writer.Write (")"); // if (!foundParamsArray && methodSymbol.Parameters.Any () && methodSymbol.Parameters.Last ().IsParams) // writer.Write (", null"); //params method called without any params argument. Send null. writer.Write(")"); }