Ejemplo n.º 1
0
        public static void Go(ScalaWriter writer, InvocationExpressionSyntax invocationExpression)
        {
            var model = Program.GetModel(invocationExpression);

            var symbolInfo       = model.GetSymbolInfo(invocationExpression);
            var expressionSymbol = model.GetSymbolInfo(invocationExpression.Expression);

            if (symbolInfo.Symbol == null)
            {
                throw new Exception("symbolInfo.Symbol null at " + Utility.Descriptor(invocationExpression));
            }
            if (symbolInfo.Symbol.OriginalDefinition == null)
            {
                throw new Exception("symbolInfo.Symbol.OriginalDefinition null at " + Utility.Descriptor(invocationExpression));
            }
            var methodSymbol = symbolInfo.Symbol.OriginalDefinition.As <IMethodSymbol>().UnReduce();

            var translateOpt = MethodTranslation.Get(symbolInfo.Symbol.As <IMethodSymbol>());
            var memberReferenceExpressionOpt = invocationExpression.Expression as MemberAccessExpressionSyntax;
            var firstParameter = true;

            var              extensionNamespace = methodSymbol.IsExtensionMethod ? methodSymbol.ContainingNamespace.FullNameWithDot() + methodSymbol.ContainingType.Name : null; //null means it's not an extension method, non-null means it is
            string           methodName;
            string           typeParameters = null;
            ExpressionSyntax subExpressionOpt;

            if (methodSymbol.ContainingType.Name == "Enum")
            {
                if (methodSymbol.Name == "Parse")
                {
                    WriteEnumParse(writer, invocationExpression);
                    return;
                }

                if (methodSymbol.Name == "TryParse")
                {
                    WriteEnumTryParse(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":
                    if (invocationExpression.ArgumentList.Arguments.Count > 1)
                    {
                        throw new Exception("Multiple arguments to .Parse methods are not supported: " + Utility.Descriptor(invocationExpression));
                    }
                    Core.Write(writer, invocationExpression.ArgumentList.Arguments.Single().Expression);

                    writer.Write(".trim().to");     //we must trim strings before parsing them.  In C#, a string like "4 " parses just fine, but if we don't trim this same string would false to parse in java
                    writer.Write(TypeProcessor.ConvertType(methodSymbol.ReturnType));

                    return;

                case "TryParse":
                    methodName         = "TryParse" + TypeProcessor.ConvertType(methodSymbol.Parameters[1].Type);
                    extensionNamespace = "CsScala";
                    break;

                default:
                    methodName         = methodSymbol.Name;
                    extensionNamespace = "CsScala";
                    break;
                }
            }
            else if (translateOpt != null && translateOpt.ReplaceWith != null)
            {
                methodName = translateOpt.ReplaceWith;
            }
            else if (methodSymbol.MethodKind == MethodKind.DelegateInvoke)
            {
                methodName = null;
            }
            else
            {
                methodName = OverloadResolver.MethodName(methodSymbol);
            }

            if (translateOpt != null && translateOpt.HasComplexReplaceWith)
            {
                translateOpt.DoComplexReplaceWith(writer, memberReferenceExpressionOpt);
                return;
            }

            if (translateOpt != null && translateOpt.SkipExtensionParameter)
            {
                subExpressionOpt = null;
            }
            else 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
            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(", ", genNameExpression.TypeArgumentList.Arguments.Select(TypeProcessor.ConvertType)) + "]";
            }


            //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 && model.GetTypeInfo(subExpressionOpt).ConvertedType.ToString() == methodSymbol.ContainingNamespace + "." + methodSymbol.ContainingType.Name)
            {
                extensionNamespace = null;
            }

            if (translateOpt != null && !string.IsNullOrEmpty(translateOpt.ExtensionNamespace))
            {
                extensionNamespace = translateOpt.ExtensionNamespace;
            }
            else if (translateOpt != null && translateOpt.ExtensionNamespace == "")
            {
                extensionNamespace = null;
            }

            var memberType     = memberReferenceExpressionOpt == null ? null : model.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";
            }


            if (extensionNamespace != null)
            {
                writer.Write(extensionNamespace);

                if (methodName != null)
                {
                    writer.Write(".");
                    writer.Write(methodName);
                }

                WriteTypeParameters(writer, translateOpt, 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.CsScala.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 (methodName != null)
                    {
                        writer.Write(".");
                    }
                }
                else if (methodSymbol.IsStatic && extensionNamespace == null)
                {
                    writer.Write(methodSymbol.ContainingNamespace.FullNameWithDot());
                    writer.Write(WriteType.TypeName(methodSymbol.ContainingType));
                    writer.Write(".");
                }


                writer.Write(methodName);
                WriteTypeParameters(writer, translateOpt, typeParameters, invocationExpression);
                writer.Write("(");
            }

            bool inParams         = false;
            bool foundParamsArray = false;

            foreach (var arg in TranslateParameters(translateOpt, invocationExpression.ArgumentList.Arguments, invocationExpression))
            {
                if (firstParameter)
                {
                    firstParameter = false;
                }
                else
                {
                    writer.Write(", ");
                }

                if (!inParams && IsParamsArgument(invocationExpression, arg.ArgumentOpt, methodSymbol))
                {
                    foundParamsArray = true;

                    if (!TypeProcessor.ConvertType(model.GetTypeInfo(arg.ArgumentOpt.Expression).Type).StartsWith("Array["))
                    {
                        inParams = true;
                        writer.Write("Array(");
                    }
                }


                if (arg.ArgumentOpt != null &&
                    arg.ArgumentOpt.RefOrOutKeyword.Kind() != SyntaxKind.None &&
                    model.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));
                }


                //When passing an argument by ref or out, leave off the .Value suffix
                if (arg.ArgumentOpt != null && arg.ArgumentOpt.RefOrOutKeyword.Kind() != SyntaxKind.None)
                {
                    WriteIdentifierName.Go(writer, arg.ArgumentOpt.Expression.As <IdentifierNameSyntax>(), true);
                }
                else
                {
                    arg.Write(writer);
                }
            }

            if (inParams)
            {
                writer.Write(")");
            }
            else if (!foundParamsArray && methodSymbol.Parameters.Any() && methodSymbol.Parameters.Last().IsParams)
            {
                writer.Write(", Array()"); //params method called without any params argument.  Send an empty array.
            }
            writer.Write(")");
        }
Ejemplo n.º 2
0
 private static void Factory(ScalaWriter writer, SyntaxNode node, bool isConst)
 {
     if (node is MethodDeclarationSyntax)
     {
         WriteMethod.Go(writer, node.As <MethodDeclarationSyntax>());
     }
     else if (node is PropertyDeclarationSyntax)
     {
         WriteProperty.Go(writer, node.As <PropertyDeclarationSyntax>());
     }
     else if (node is FieldDeclarationSyntax)
     {
         WriteField.Go(writer, node.As <FieldDeclarationSyntax>());
     }
     else if (node is ConstructorDeclarationSyntax)
     {
         WriteConstructorBody.Go(writer, node.As <ConstructorDeclarationSyntax>());
     }
     else if (node is ExpressionStatementSyntax)
     {
         WriteStatement(writer, node.As <ExpressionStatementSyntax>());
     }
     else if (node is LocalDeclarationStatementSyntax)
     {
         WriteLocalDeclaration.Go(writer, node.As <LocalDeclarationStatementSyntax>());
     }
     else if (node is BlockSyntax)
     {
         WriteBlock(writer, node.As <BlockSyntax>());
     }
     else if (node is InvocationExpressionSyntax)
     {
         WriteInvocationExpression.Go(writer, node.As <InvocationExpressionSyntax>());
     }
     else if (node is LiteralExpressionSyntax)
     {
         WriteLiteralExpression.Go(writer, node.As <LiteralExpressionSyntax>(), isConst);
     }
     else if (node is IdentifierNameSyntax)
     {
         WriteIdentifierName.Go(writer, node.As <IdentifierNameSyntax>());
     }
     else if (node is ImplicitArrayCreationExpressionSyntax)
     {
         WriteArrayCreationExpression.Go(writer, node.As <ImplicitArrayCreationExpressionSyntax>());
     }
     else if (node is ArrayCreationExpressionSyntax)
     {
         WriteArrayCreationExpression.Go(writer, node.As <ArrayCreationExpressionSyntax>());
     }
     else if (node is MemberAccessExpressionSyntax)
     {
         WriteMemberAccessExpression.Go(writer, node.As <MemberAccessExpressionSyntax>());
     }
     else if (node is ParenthesizedLambdaExpressionSyntax)
     {
         WriteLambdaExpression.Go(writer, node.As <ParenthesizedLambdaExpressionSyntax>());
     }
     else if (node is SimpleLambdaExpressionSyntax)
     {
         WriteLambdaExpression.Go(writer, node.As <SimpleLambdaExpressionSyntax>());
     }
     else if (node is ReturnStatementSyntax)
     {
         WriteReturnStatement.Go(writer, node.As <ReturnStatementSyntax>());
     }
     else if (node is ObjectCreationExpressionSyntax)
     {
         WriteObjectCreationExpression.Go(writer, node.As <ObjectCreationExpressionSyntax>());
     }
     else if (node is ElementAccessExpressionSyntax)
     {
         WriteElementAccessExpression.Go(writer, node.As <ElementAccessExpressionSyntax>());
     }
     else if (node is ForEachStatementSyntax)
     {
         WriteForEachStatement.Go(writer, node.As <ForEachStatementSyntax>());
     }
     else if (node is IfStatementSyntax)
     {
         WriteIfStatement.Go(writer, node.As <IfStatementSyntax>());
     }
     else if (node is BinaryExpressionSyntax)
     {
         WriteBinaryExpression.Go(writer, node.As <BinaryExpressionSyntax>());
     }
     else if (node is AssignmentExpressionSyntax)
     {
         WriteBinaryExpression.Go(writer, node.As <AssignmentExpressionSyntax>());
     }
     else if (node is ConditionalExpressionSyntax)
     {
         WriteConditionalExpression.Go(writer, node.As <ConditionalExpressionSyntax>());
     }
     else if (node is BaseExpressionSyntax)
     {
         WriteBaseExpression.Go(writer, node.As <BaseExpressionSyntax>());
     }
     else if (node is ThisExpressionSyntax)
     {
         WriteThisExpression.Go(writer, node.As <ThisExpressionSyntax>());
     }
     else if (node is CastExpressionSyntax)
     {
         WriteCastExpression.Go(writer, node.As <CastExpressionSyntax>());
     }
     else if (node is ThrowStatementSyntax)
     {
         WriteThrowStatement.Go(writer, node.As <ThrowStatementSyntax>());
     }
     else if (node is ThrowExpressionSyntax)
     {
         WriteThrowStatement.WriteThrowExpression(writer, node.As <ThrowExpressionSyntax>());
     }
     else if (node is EqualsValueClauseSyntax)
     {
         WriteEqualsValueClause.Go(writer, node.As <EqualsValueClauseSyntax>());
     }
     else if (node is ForStatementSyntax)
     {
         WriteForStatement.Go(writer, node.As <ForStatementSyntax>());
     }
     else if (node is WhileStatementSyntax)
     {
         WriteWhileStatement.Go(writer, node.As <WhileStatementSyntax>());
     }
     else if (node is BreakStatementSyntax)
     {
         WriteBreakStatement.Go(writer, node.As <BreakStatementSyntax>());
     }
     else if (node is ContinueStatementSyntax)
     {
         WriteContinueStatement.Go(writer, node.As <ContinueStatementSyntax>());
     }
     else if (node is DoStatementSyntax)
     {
         WriteDoStatement.Go(writer, node.As <DoStatementSyntax>());
     }
     else if (node is SwitchStatementSyntax)
     {
         WriteSwitchStatement.Go(writer, node.As <SwitchStatementSyntax>());
     }
     else if (node is TryStatementSyntax)
     {
         WriteTryStatement.Go(writer, node.As <TryStatementSyntax>());
     }
     else if (node is UsingStatementSyntax)
     {
         WriteUsingStatement.Go(writer, node.As <UsingStatementSyntax>());
     }
     else if (node is ParenthesizedExpressionSyntax)
     {
         WriteParenthesizedExpression.Go(writer, node.As <ParenthesizedExpressionSyntax>());
     }
     else if (node is LockStatementSyntax)
     {
         WriteLockStatement.Go(writer, node.As <LockStatementSyntax>());
     }
     else if (node is TypeOfExpressionSyntax)
     {
         WriteTypeOfExpression.Go(writer, node.As <TypeOfExpressionSyntax>());
     }
     else if (node is AnonymousObjectCreationExpressionSyntax)
     {
         WriteAnonymousObjectCreationExpression.Go(writer, node.As <AnonymousObjectCreationExpressionSyntax>());
     }
     else if (node is EmptyStatementSyntax)
     {
         return; //ignore empty statements
     }
     else if (node is DelegateDeclarationSyntax)
     {
         return; //don't write delegates - TypeProcessor converts them to function types directly
     }
     else if (node is DefaultExpressionSyntax)
     {
         WriteDefaultExpression.Go(writer, node.As <DefaultExpressionSyntax>());
     }
     else if (node is GenericNameSyntax)
     {
         WriteGenericName.Go(writer, node.As <GenericNameSyntax>());
     }
     else if (node is ConversionOperatorDeclarationSyntax)
     {
         WriteConversionOperatorDeclaration.Go(writer, node.As <ConversionOperatorDeclarationSyntax>());
     }
     else if (node is PrefixUnaryExpressionSyntax)
     {
         WriteUnaryExpression.WritePrefix(writer, node.As <PrefixUnaryExpressionSyntax>());
     }
     else if (node is PostfixUnaryExpressionSyntax)
     {
         WriteUnaryExpression.WritePostfix(writer, node.As <PostfixUnaryExpressionSyntax>());
     }
     else if (node is SizeOfExpressionSyntax)
     {
         WriteSizeOfExpression.Go(writer, node.As <SizeOfExpressionSyntax>());
     }
     else
     {
         throw new NotImplementedException(node.GetType().Name + " is not supported. " + Utility.Descriptor(node));
     }
 }