Beispiel #1
0
        public static void Go()
        {
            var partials = TypeState.Instance.Partials;
            var first    = partials.First();



            using (var writer = new ScalaWriter(first.Symbol.ContainingNamespace.FullName(), TypeState.Instance.TypeName))
            {
                var bases = partials
                            .Select(o => o.Syntax.BaseList)
                            .Where(o => o != null)
                            .SelectMany(o => o.Types)
                            .Select(o => Program.GetModel(o).GetTypeInfo(o.Type).ConvertedType)
                            .Distinct()
                            .ToList();

                var interfaces = bases.Where(o => o.TypeKind == TypeKind.Interface).ToList();

                //TypeState.Instance.DerivesFromObject = bases.Count == interfaces.Count;

                var package = first.Symbol.ContainingNamespace.FullName();
                if (package.Length > 0)
                {
                    writer.WriteLine("package " + package + @";");
                }

                WriteImports.Go(writer);

                if (first.Syntax is EnumDeclarationSyntax)
                {
                    WriteEnum.Go(writer, TypeState.Instance.Partials.Select(o => o.Syntax).Cast <EnumDeclarationSyntax>().SelectMany(o => o.Members).Where(o => !Program.DoNotWrite.ContainsKey(o)));
                    return;
                }


                TypeState.Instance.AllMembers = partials.Select(o => o.Syntax).Cast <TypeDeclarationSyntax>().SelectMany(o => o.Members).Where(o => !Program.DoNotWrite.ContainsKey(o)).ToList();

                var allMembersToWrite = TypeState.Instance.AllMembers
                                        .Where(member => !(member is TypeDeclarationSyntax) &&
                                               !(member is EnumDeclarationSyntax) &&
                                               !(member is DelegateDeclarationSyntax))
                                        .ToList();

                var instanceCtors = TypeState.Instance.AllMembers.OfType <ConstructorDeclarationSyntax>()
                                    .Where(o => !o.Modifiers.Any(SyntaxKind.StaticKeyword))
                                    .ToList();

                if (instanceCtors.Count > 1)
                {
                    throw new Exception("Overloaded constructors are not supported.  Consider changing all but one to static Create methods " + Utility.Descriptor(first.Syntax));
                }

                var ctorOpt = instanceCtors.SingleOrDefault();

                foreach (var staticMembers in new[] { true, false })
                {
                    var membersToWrite = allMembersToWrite.Where(o => IsStatic(o) == staticMembers).ToList();

                    if (membersToWrite.Count == 0 && (staticMembers || partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.StaticKeyword))))
                    {
                        continue;
                    }

                    if (staticMembers)
                    {
                        writer.Write("object ");
                    }
                    else if (first.Syntax.Kind() == SyntaxKind.InterfaceDeclaration)
                    {
                        writer.Write("trait ");
                    }
                    else
                    {
                        if (partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.AbstractKeyword)))
                        {
                            writer.Write("abstract ");
                        }

                        writer.Write("class ");
                    }

                    writer.Write(TypeState.Instance.TypeName);



                    if (!staticMembers && first.Syntax is TypeDeclarationSyntax)
                    {
                        //Look for generic arguments
                        var genericArgs = partials
                                          .Select(o => o.Syntax)
                                          .Cast <TypeDeclarationSyntax>()
                                          .Where(o => o.TypeParameterList != null)
                                          .SelectMany(o => o.TypeParameterList.Parameters)
                                          .ToList();

                        if (genericArgs.Count > 0)
                        {
                            writer.Write("[");
                            writer.Write(string.Join(", ", genericArgs.Select(o => TypeParameter(o))));
                            writer.Write("]");
                        }

                        //Write constructor arguments
                        if (ctorOpt != null && ctorOpt.ParameterList.Parameters.Count > 0)
                        {
                            writer.Write("(");
                            var firstParameter = true;
                            foreach (var parameter in ctorOpt.ParameterList.Parameters)
                            {
                                if (firstParameter)
                                {
                                    firstParameter = false;
                                }
                                else
                                {
                                    writer.Write(", ");
                                }

                                writer.Write(WriteIdentifierName.TransformIdentifier(parameter.Identifier.ValueText));
                                writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type));

                                if (parameter.Default != null)
                                {
                                    writer.Write(" = ");
                                    Core.Write(writer, parameter.Default.Value);
                                }
                            }
                            writer.Write(")");
                        }

                        bool firstBase = true;
                        foreach (var baseType in bases.OrderBy(o => o.TypeKind == TypeKind.Interface ? 1 : 0))
                        {
                            if (firstBase)
                            {
                                writer.Write(" extends ");
                            }
                            else
                            {
                                writer.Write(" with ");
                            }

                            writer.Write(TypeProcessor.ConvertType(baseType));


                            if (firstBase && ctorOpt != null && ctorOpt.Initializer != null && ctorOpt.Initializer.ArgumentList.Arguments.Count > 0)
                            {
                                writer.Write("(");
                                bool firstArg = true;
                                foreach (var init in ctorOpt.Initializer.ArgumentList.Arguments)
                                {
                                    if (firstArg)
                                    {
                                        firstArg = false;
                                    }
                                    else
                                    {
                                        writer.Write(", ");
                                    }

                                    Core.Write(writer, init.Expression);
                                }
                                writer.Write(")");
                            }

                            firstBase = false;
                        }
                    }

                    writer.Write("\r\n");

                    writer.WriteOpenBrace();

                    var fields    = membersToWrite.OfType <FieldDeclarationSyntax>().ToList();
                    var nonFields = membersToWrite.Except(fields);

                    fields = SortFields(fields);

                    foreach (var member in fields)
                    {
                        Core.Write(writer, member);
                    }
                    foreach (var member in nonFields)
                    {
                        Core.Write(writer, member);
                    }


                    if (!staticMembers && ctorOpt != null && ctorOpt.Body != null && ctorOpt.Body.As <BlockSyntax>().Statements.Count > 0)
                    {
                        writer.WriteLine();
                        Core.WriteBlock(writer, ctorOpt.Body.As <BlockSyntax>(), true); //render braces so local ctor variables don't bleed out into fields
                    }


                    writer.WriteCloseBrace();
                }
            }
        }
        private static void Go(ScalaWriter writer, ExpressionSyntax left, SyntaxToken operatorToken, ExpressionSyntax right)
        {
            if (operatorToken.Kind() == SyntaxKind.AsKeyword)
            {
                writer.Write("CsScala.As[");
                writer.Write(TypeProcessor.ConvertType(right));
                writer.Write("](");
                Core.Write(writer, left);
                writer.Write(")");
            }
            else if (operatorToken.Kind() == SyntaxKind.IsKeyword)
            {
                Core.Write(writer, left);
                writer.Write(".isInstanceOf[");
                writer.Write(TypeProcessor.ConvertType(right));
                writer.Write("]");
            }
            else if (operatorToken.Kind() == SyntaxKind.QuestionQuestionToken)
            {
                writer.Write("CsScala.Coalesce(");
                Core.Write(writer, left);
                writer.Write(", ");
                Core.Write(writer, right);
                writer.Write(")");
            }
            else
            {
                if (left is ElementAccessExpressionSyntax && IsAssignmentToken(operatorToken.Kind()))
                {
                    var subExpr = left.As <ElementAccessExpressionSyntax>();
                    var typeStr = TypeProcessor.GenericTypeName(Program.GetModel(left).GetTypeInfo(subExpr.Expression).Type);
                    var trans   = ElementAccessTranslation.Get(typeStr);

                    if (trans != null)
                    {
                        Core.Write(writer, subExpr.Expression);
                        writer.Write(".");

                        if (operatorToken.Kind() == SyntaxKind.EqualsToken)
                        {
                            writer.Write(trans.ReplaceAssign);
                        }
                        else
                        {
                            throw new Exception(operatorToken.Kind() + " is not supported on " + typeStr + " " + Utility.Descriptor(left.Parent));
                        }

                        writer.Write("(");
                        foreach (var arg in subExpr.ArgumentList.Arguments)
                        {
                            Core.Write(writer, arg.Expression);
                            writer.Write(", ");
                        }

                        Core.Write(writer, right);
                        writer.Write(")");

                        return;
                    }
                }

                Action <ExpressionSyntax> write = e =>
                {
                    var model = Program.GetModel(left);
                    var type  = model.GetTypeInfo(e);

                    //Check for enums being converted to strings by string concatenation
                    if (operatorToken.Kind() == SyntaxKind.PlusToken && type.Type.TypeKind == TypeKind.Enum)
                    {
                        writer.Write(type.Type.ContainingNamespace.FullNameWithDot());
                        writer.Write(WriteType.TypeName(type.Type.As <INamedTypeSymbol>()));
                        writer.Write(".ToString(");
                        Core.Write(writer, e);
                        writer.Write(")");
                    }
                    else if (operatorToken.Kind() == SyntaxKind.PlusToken && (type.Type.Name == "Nullable" && type.Type.ContainingNamespace.FullName() == "System" && type.Type.As <INamedTypeSymbol>().TypeArguments.Single().TypeKind == TypeKind.Enum))
                    {
                        var enumType = type.Type.As <INamedTypeSymbol>().TypeArguments.Single();
                        writer.Write(enumType.ContainingNamespace.FullNameWithDot());
                        writer.Write(WriteType.TypeName(enumType.As <INamedTypeSymbol>()));
                        writer.Write(".ToString(");
                        Core.Write(writer, e);
                        writer.Write(")");
                    }
                    else if (operatorToken.Kind() == SyntaxKind.PlusToken && IsException(type.Type))     //Check for exceptions being converted to strings by string concatenation
                    {
                        writer.Write("System.CsScala.ExceptionToString(");
                        Core.Write(writer, e);
                        writer.Write(")");
                    }
                    else if (operatorToken.Kind() == SyntaxKind.PlusToken && type.Type.SpecialType == SpecialType.System_Byte && !Utility.IsNumeric(type.ConvertedType))
                    {
                        //bytes are signed in the JVM, so we need to take care when converting them to strings.  Exclude numeric types, since Core.Writer will convert these to ints
                        writer.Write("System.CsScala.ByteToString(");
                        Core.Write(writer, e);
                        writer.Write(")");
                    }
                    else if (operatorToken.Kind() == SyntaxKind.PlusToken && !(e is BinaryExpressionSyntax) && type.Type.SpecialType == SpecialType.System_String && CouldBeNullString(model, e))
                    {
                        //In .net, concatenating a null string does not alter the output. However, in the JVM, it produces the "null" string. To counter this, we must check non-const strings.
                        writer.Write("System.CsScala.NullCheck(");
                        Core.Write(writer, e);
                        writer.Write(")");
                    }
                    else if (operatorToken.Kind() == SyntaxKind.PlusToken && !(e is BinaryExpressionSyntax) && type.Type is INamedTypeSymbol && type.Type.As <INamedTypeSymbol>().ConstructedFrom.SpecialType == SpecialType.System_Nullable_T)
                    {
                        //Concatening a nullable type in .net just produces an empty string if it's null.  In scala it produces "null" or a null reference exception -- we want neither.
                        writer.Write("System.CsScala.NullCheck(");
                        Core.Write(writer, e);
                        writer.Write(")");
                    }
                    else if (operatorToken.Kind() == SyntaxKind.PlusToken && !(e is BinaryExpressionSyntax) && type.Type.SpecialType == SpecialType.System_Boolean)
                    {
                        writer.Write("System.CsScala.BooleanToString(");
                        Core.Write(writer, e);
                        writer.Write(")");
                    }
                    else
                    {
                        Core.Write(writer, e);
                    }
                };

                write(left);
                writer.Write(" ");
                writer.Write(operatorToken.ToString());
                writer.Write(" ");
                write(right);
            }
        }
Beispiel #3
0
        public static void Go(ScalaWriter writer, MethodDeclarationSyntax method)
        {
            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 (TypeState.Instance.Partials.SelectMany(o => o.Syntax.As <ClassDeclarationSyntax>().Members)
                    .OfType <MethodDeclarationSyntax>()
                    .Except(method)
                    .Where(o => o.Identifier.ValueText == method.Identifier.ValueText)
                    .Any())
                {
                    return;
                }
            }

            var methodSymbol = Program.GetModel(method).GetDeclaredSymbol(method);


            if (method.Identifier.ValueText == "GetEnumerator")
            {
                WriteGetEnumeratorFunction(writer, method, methodSymbol);
                return;
            }


            writer.WriteIndent();

            if (ShouldUseOverrideKeyword(method, methodSymbol))
            {
                writer.Write("override ");
            }
            if (method.Modifiers.Any(SyntaxKind.PrivateKeyword))
            {
                writer.Write("private ");
            }

            writer.Write("def ");
            var methodName = OverloadResolver.MethodName(methodSymbol);

            if (methodName == "ToString")
            {
                methodName = "toString";
            }
            else if (methodName == "Equals")
            {
                methodName = "equals";
            }
            else if (methodName == "GetHashCode")
            {
                methodName = "hashCode";
            }
            else if (methodName == "Main")
            {
                methodName = "main";
            }

            writer.Write(methodName);

            if (method.TypeParameterList != null)
            {
                writer.Write("[");
                writer.Write(string.Join(", ", method.TypeParameterList.Parameters.Select(o => TypeParameter(o, methodSymbol, method))));
                writer.Write("]");
            }

            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(", ");
                }

                writer.Write(WriteIdentifierName.TransformIdentifier(parameter.Identifier.ValueText));

                if (isRef)
                {
                    writer.Write(":CsRef[");
                    writer.Write(TypeProcessor.ConvertType(parameter.Type));
                    writer.Write("]");

                    Program.RefOutSymbols.TryAdd(Program.GetModel(method).GetDeclaredSymbol(parameter), null);
                }
                else
                {
                    writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type));
                }

                if (parameter.Default != null)
                {
                    writer.Write(" = ");
                    Core.Write(writer, parameter.Default.Value);
                }
            }

            writer.Write(")");
            bool returnsVoid = method.ReturnType.ToString() == "void";

            if (!returnsVoid)
            {
                writer.Write(TypeProcessor.ConvertTypeWithColon(method.ReturnType));
            }

            if (method.Modifiers.Any(SyntaxKind.AbstractKeyword) || method.Parent is InterfaceDeclarationSyntax)
            {
                writer.Write(";\r\n");
            }
            else
            {
                if (!returnsVoid)
                {
                    writer.Write(" =");
                }

                writer.Write("\r\n");
                writer.WriteOpenBrace();

                if (method.Body != null)
                {
                    foreach (var statement in method.Body.Statements)
                    {
                        Core.Write(writer, statement);
                    }

                    TriviaProcessor.ProcessTrivias(writer, method.Body.DescendantTrivia());
                }

                writer.WriteCloseBrace();
            }
        }
Beispiel #4
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(")");
        }
Beispiel #5
0
        public static void Go(ScalaWriter writer, MemberAccessExpressionSyntax expression)
        {
            var model = Program.GetModel(expression);

            var memberName = expression.Name.Identifier.ValueText;
            var type       = model.GetTypeInfo(expression.Expression).ConvertedType;
            var typeStr    = TypeProcessor.GenericTypeName(type);

            if (expression.Expression is PredefinedTypeSyntax)
            {
                if (memberName == "MaxValue" || memberName == "MinValue" || memberName == "NaN")
                {
                    var predefined = expression.Expression.ToString();

                    if (predefined.StartsWith("u"))
                    {
                        //Scala does not have unsigned types. Forward these to CsScala
                        writer.Write("System.CsScala.");
                        writer.Write(predefined);
                        writer.Write(memberName);
                    }
                    else
                    {
                        writer.Write(predefined[0].ToString().ToUpper());
                        writer.Write(predefined.Substring(1));
                        writer.Write(".");
                        writer.Write(memberName);
                    }
                }
                else
                {
                    var field = System.Type.GetType(typeStr).GetField(memberName);

                    if (field == null)
                    {
                        throw new Exception("Cannot use " + memberName + " as a field.  If you're passing a function, wrap a closure around it. " + Utility.Descriptor(expression));
                    }
                    var val = field.GetValue(null);
                    if (val is string)
                    {
                        writer.Write("\"" + val + "\"");
                    }
                    else
                    {
                        writer.Write(val.ToString());
                    }
                }
            }
            else if (type.OriginalDefinition is INamedTypeSymbol && type.OriginalDefinition.As <INamedTypeSymbol>().SpecialType == SpecialType.System_Nullable_T)
            {
                switch (memberName)
                {
                case "HasValue":
                    writer.Write("(");
                    WriteMember(writer, expression.Expression);
                    writer.Write(" != null)");
                    break;

                case "Value":
                    var nullableType = TypeProcessor.ConvertType(type.As <INamedTypeSymbol>().TypeArguments.Single());
                    WriteMember(writer, expression.Expression);

                    if (TypeProcessor.IsPrimitiveType(nullableType))
                    {
                        writer.Write(".");
                        writer.Write(nullableType[0].ToString().ToLower());
                        writer.Write(nullableType.Substring(1));
                        writer.Write("Value()");
                    }
                    break;

                default:
                    throw new Exception("Need handler for Nullable." + memberName + " " + Utility.Descriptor(expression));
                }
            }
            else
            {
                var translate = PropertyTranslation.Get(typeStr, memberName);

                if (translate != null && translate.ExtensionMethod != null)
                {
                    writer.Write(translate.ExtensionMethod);
                    writer.Write("(");
                    if (!(model.GetSymbolInfo(expression.Expression).Symbol is INamedTypeSymbol))
                    {
                        Core.Write(writer, expression.Expression);
                    }
                    writer.Write(")");
                    return;
                }

                if (translate != null)
                {
                    memberName = translate.ReplaceWith;
                }
                else
                {
                    memberName = WriteIdentifierName.TransformIdentifier(memberName);
                }

                if (type != null) //if type is null, then we're just a namespace.  We can ignore these.
                {
                    WriteMember(writer, expression.Expression);
                    writer.Write(".");
                }

                writer.Write(memberName);

                if (expression.Name is GenericNameSyntax)
                {
                    var gen = expression.Name.As <GenericNameSyntax>();

                    writer.Write("[");

                    bool first = true;
                    foreach (var g in gen.TypeArgumentList.Arguments)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            writer.Write(", ");
                        }

                        writer.Write(TypeProcessor.ConvertTypeWithColon(g));
                    }

                    writer.Write("]");
                }
            }
        }
        private static void Go(ScalaWriter writer, IEnumerable <ParameterSyntax> parameters, SyntaxNode body, TypeInfo type)
        {
            var methodSymbol = type.ConvertedType.As <INamedTypeSymbol>().DelegateInvokeMethod.As <IMethodSymbol>();

            writer.Write("(");

            for (int pi = 0; pi < parameters.Count(); pi++)
            {
                var parameter = parameters.ElementAt(pi);
                if (pi > 0)
                {
                    writer.Write(", ");
                }

                writer.Write(WriteIdentifierName.TransformIdentifier(parameter.Identifier.ValueText));
                if (parameter.Type != null)
                {
                    writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type));
                }
                else
                {
                    writer.Write(TypeProcessor.ConvertTypeWithColon(methodSymbol.Parameters[pi].Type));
                }
            }

            writer.Write(") => ");

            bool returnsVoid = methodSymbol.ReturnType.ToString() == "void";

            if (body is BlockSyntax)
            {
                writer.Write("\r\n");
                writer.WriteOpenBrace();

                var statements = body.As <BlockSyntax>().Statements;

                var lastStatement = statements.LastOrDefault() as ReturnStatementSyntax;

                var returnStatements = FindReturnStatements(body);

                if (returnStatements.Count > 0 && (lastStatement == null || returnStatements.Except(lastStatement).Any()))
                {
                    //Lambda has branching returns.  We must use a breakable block since scala can't return from a lambda like C# can
                    TypeState.Instance.InLambdaBreakable++;

                    writer.WriteLine("val __lambdabreak = new Breaks;");

                    if (!returnsVoid)
                    {
                        writer.WriteIndent();
                        writer.Write("var __lambdareturn:");
                        writer.Write(TypeProcessor.ConvertType(methodSymbol.ReturnType));
                        writer.Write(" = ");
                        writer.Write(TypeProcessor.DefaultValue(methodSymbol.ReturnType));
                        writer.Write(";\r\n");
                    }

                    writer.WriteLine("__lambdabreak.breakable");
                    writer.WriteOpenBrace();

                    foreach (var statement in statements)
                    {
                        if (statement == lastStatement && !returnsVoid)
                        {
                            //Manually write it so we avoid the final break that WriteReturnStatement does
                            writer.WriteIndent();
                            writer.Write("__lambdareturn = ");
                            Core.Write(writer, lastStatement.Expression);
                            writer.Write(";\r\n");
                        }
                        else
                        {
                            Core.Write(writer, statement);
                        }
                    }

                    TriviaProcessor.ProcessTrivias(writer, body.DescendantTrivia());

                    writer.WriteCloseBrace();

                    if (!returnsVoid)
                    {
                        writer.WriteLine("__lambdareturn;");
                    }

                    TypeState.Instance.InLambdaBreakable--;
                }
                else
                {
                    foreach (var statement in statements)
                    {
                        if (statement == lastStatement)
                        {
                            writer.WriteIndent();
                            Core.Write(writer, lastStatement.Expression);
                            writer.Write(";\r\n");
                        }
                        else
                        {
                            Core.Write(writer, statement);
                        }
                    }
                }

                writer.Indent--;
                writer.WriteIndent();
                writer.Write("}");
            }
            else
            {
                writer.Write(" { ");
                Core.Write(writer, body);
                writer.Write("; }");
            }

            if (!returnsVoid)
            {
                writer.Write(TypeProcessor.ConvertTypeWithColon(methodSymbol.ReturnType));
            }
        }