예제 #1
0
        public static void Go(ScalaWriter writer, ElementAccessExpressionSyntax expression)
        {
            var typeStr = TypeProcessor.GenericTypeName(Program.GetModel(expression).GetTypeInfo(expression.Expression).Type);
            var trans   = ElementAccessTranslation.Get(typeStr);

            Core.Write(writer, expression.Expression);

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

            writer.Write("(");

            bool first = true;

            foreach (var argument in expression.ArgumentList.Arguments)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    writer.Write(", ");
                }

                Core.Write(writer, argument.Expression);
            }
            writer.Write(")");
        }
        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);
            }
        }