Beispiel #1
0
        private ExpressionSyntax DeconstructionToMethod(SemanticModel model, ExpressionSyntax tuple, ExpressionSyntax obj, DeconstructionInfo deconstructionInfo)
        {
            List <ArgumentSyntax> arguments = new List <ArgumentSyntax>();

            if (tuple is TupleExpressionSyntax te)
            {
                foreach (var arg in te.Arguments)
                {
                    try
                    {
                        if (arg.Expression is DeclarationExpressionSyntax de)
                        {
                            if (de.Designation is SingleVariableDesignationSyntax sv)
                            {
                                arguments.Add(SyntaxFactory.Argument(SyntaxFactory.IdentifierName(sv.Identifier)).WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(
                                                  SyntaxFactory.Token(SyntaxKind.OutKeyword)));
                            }
                        }
                        else
                        {
                            arguments.Add(arg.WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(
                                              SyntaxFactory.Token(SyntaxKind.OutKeyword)));
                        }
                    }
                    catch (Exception e)
                    {
                        throw new ReplacerException(arg, e);
                    }
                }
            }
            else
            {
                var variables = ((ParenthesizedVariableDesignationSyntax)((DeclarationExpressionSyntax)tuple).Designation).Variables;
                foreach (var variable in variables)
                {
                    try
                    {
                        if (variable is SingleVariableDesignationSyntax sv)
                        {
                            arguments.Add(SyntaxFactory.Argument(SyntaxFactory.IdentifierName(sv.Identifier)).WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(
                                              SyntaxFactory.Token(SyntaxKind.OutKeyword)));
                        }
                    }
                    catch (Exception e)
                    {
                        throw new ReplacerException(variable, e);
                    }
                }
            }

            if (deconstructionInfo.Method != null)
            {
                if (deconstructionInfo.Method.IsExtensionMethod)
                {
                    arguments.Insert(0, SyntaxFactory.Argument(obj));
                    return(SyntaxHelper.GenerateInvocation(deconstructionInfo.Method.Name, deconstructionInfo.Method.ContainingType.FullyQualifiedName(), arguments.ToArray()).NormalizeWhitespace());
                }
                else
                {
                    return(SyntaxHelper.GenerateInvocation(deconstructionInfo.Method.Name, obj, arguments.ToArray()).NormalizeWhitespace());
                }
            }
            else
            {
                arguments.Insert(0, SyntaxFactory.Argument(obj));
                return(SyntaxHelper.GenerateInvocation("Deconstruct", "H5.Script", arguments.ToArray()).NormalizeWhitespace());
            }
        }
Beispiel #2
0
        public SyntaxNode InsertVariables(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter)
        {
            var tuples = root
                         .DescendantNodes()
                         .OfType <TupleExpressionSyntax>()
                         .Where(e => e.Parent is AssignmentExpressionSyntax ae && ae.Left == e || e.Parent is ForEachVariableStatementSyntax fe && fe.Variable == e);

            var updatedStatements = new Dictionary <StatementSyntax, List <LocalDeclarationStatementSyntax> >();

            foreach (var tuple in tuples)
            {
                try
                {
                    var beforeStatement = tuple.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                    if (beforeStatement != null)
                    {
                        foreach (var arg in tuple.Arguments)
                        {
                            if (arg.Expression is DeclarationExpressionSyntax de)
                            {
                                if (de.Designation is SingleVariableDesignationSyntax designation)
                                {
                                    var locals   = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();
                                    var typeInfo = model.GetTypeInfo(de).Type;
                                    var varDecl  = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo, model, arg.Expression.GetLocation().SourceSpan.Start, rewriter)).WithVariables(SyntaxFactory.SingletonSeparatedList(
                                                                                                                                                                                                                  SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(designation.Identifier.ValueText))
                                                                                                                                                                                                                  ));

                                    locals.Add(SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")));

                                    updatedStatements[beforeStatement] = locals;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(tuple, e);
                }
            }

            var parenthesized = root
                                .DescendantNodes()
                                .OfType <ParenthesizedVariableDesignationSyntax>()
                                .Where(e => e.Parent is DeclarationExpressionSyntax && e.Parent.Parent is AssignmentExpressionSyntax ae && ae.Left == e.Parent ||
                                       e.Parent is DeclarationExpressionSyntax && e.Parent.Parent is ForEachVariableStatementSyntax fe && fe.Variable == e.Parent);

            foreach (var p in parenthesized)
            {
                try
                {
                    var beforeStatement = p.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                    var declaration     = (DeclarationExpressionSyntax)p.Parent;
                    if (beforeStatement != null)
                    {
                        var typeInfo            = model.GetTypeInfo(declaration).Type;
                        List <TypeSyntax> types = new List <TypeSyntax>();
                        if (typeInfo.IsTupleType)
                        {
                            var elements = ((INamedTypeSymbol)typeInfo).TupleElements;
                            foreach (var el in elements)
                            {
                                types.Add(SyntaxHelper.GenerateTypeSyntax(el.Type, model, declaration.GetLocation().SourceSpan.Start, rewriter));
                            }
                        }
                        else
                        {
                            continue;
                        }

                        int idx = 0;
                        foreach (var v in p.Variables)
                        {
                            if (v is SingleVariableDesignationSyntax designation)
                            {
                                var locals = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();

                                var varDecl = SyntaxFactory.VariableDeclaration(types[idx++]).WithVariables(SyntaxFactory.SingletonSeparatedList(
                                                                                                                SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(designation.Identifier.ValueText))
                                                                                                                ));

                                locals.Add(SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")));

                                updatedStatements[beforeStatement] = locals;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(p, e);
                }
            }

            var annotated = new Dictionary <SyntaxAnnotation, List <LocalDeclarationStatementSyntax> >();

            root = root.ReplaceNodes(updatedStatements.Keys, (n1, n2) =>
            {
                var annotation        = new SyntaxAnnotation();
                annotated[annotation] = updatedStatements[n1];

                n2 = n2.WithAdditionalAnnotations(annotation);
                return(n2);
            });

            foreach (var annotation in annotated.Keys)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                var varStatements = annotated[annotation];

                if (annotatedNode is ForEachVariableStatementSyntax fe)
                {
                    varStatements[varStatements.Count - 1] = varStatements.Last().WithAdditionalAnnotations(new SyntaxAnnotation("last_variable"));
                    var list = new List <StatementSyntax>(varStatements);

                    if (fe.Statement is BlockSyntax b)
                    {
                        list.AddRange(b.Statements);
                    }
                    else
                    {
                        list.Add(fe.Statement);
                    }

                    root = root.ReplaceNode(annotatedNode, fe.WithStatement(SyntaxFactory.Block(list)).NormalizeWhitespace());
                }
                else if (annotatedNode.Parent is BlockSyntax || !(annotatedNode is StatementSyntax))
                {
                    root = root.InsertNodesBefore(annotatedNode, varStatements);
                }
                else
                {
                    var list = new List <StatementSyntax>(varStatements);
                    list.Add((StatementSyntax)annotatedNode);
                    root = root.ReplaceNode(annotatedNode, SyntaxFactory.Block(list).NormalizeWhitespace());
                }
            }

            return(root);
        }
Beispiel #3
0
        protected void VisitUnaryOperatorExpression()
        {
            var  unaryOperatorExpression = UnaryOperatorExpression;
            var  oldType              = Emitter.UnaryOperatorType;
            var  oldAccessor          = Emitter.IsUnaryAccessor;
            var  resolveOperator      = Emitter.Resolver.ResolveNode(unaryOperatorExpression);
            var  expectedType         = Emitter.Resolver.Resolver.GetExpectedType(unaryOperatorExpression);
            bool isDecimalExpected    = Helpers.IsDecimalType(expectedType, Emitter.Resolver);
            bool isDecimal            = Helpers.IsDecimalType(resolveOperator.Type, Emitter.Resolver);
            bool isLongExpected       = Helpers.Is64Type(expectedType, Emitter.Resolver);
            bool isLong               = Helpers.Is64Type(resolveOperator.Type, Emitter.Resolver);
            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
            int count = Emitter.Writers.Count;

            if (resolveOperator is ConstantResolveResult crr)
            {
                object constantValue = crr.ConstantValue;

                if (unaryOperatorExpression.Operator == UnaryOperatorType.Minus && SyntaxHelper.IsNumeric(constantValue.GetType()) && Convert.ToDouble(constantValue) == 0)
                {
                    Write("-");
                }

                WriteScript(constantValue);
                return;
            }

            if (Helpers.IsDecimalType(resolveOperator.Type, Emitter.Resolver))
            {
                isDecimal         = true;
                isDecimalExpected = true;
            }

            if (isDecimal && isDecimalExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await)
            {
                HandleDecimal(resolveOperator);
                return;
            }

            if (ResolveOperator(unaryOperatorExpression, orr))
            {
                return;
            }

            if (Helpers.Is64Type(resolveOperator.Type, Emitter.Resolver))
            {
                isLong         = true;
                isLongExpected = true;
            }

            if (isLong && isLongExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await)
            {
                HandleDecimal(resolveOperator, true);
                return;
            }

            if (ResolveOperator(unaryOperatorExpression, orr))
            {
                return;
            }

            var  op = unaryOperatorExpression.Operator;
            var  argResolverResult = Emitter.Resolver.ResolveNode(unaryOperatorExpression.Expression);
            bool nullable          = NullableType.IsNullable(argResolverResult.Type);

            if (nullable)
            {
                if (op != UnaryOperatorType.Increment &&
                    op != UnaryOperatorType.Decrement &&
                    op != UnaryOperatorType.PostIncrement &&
                    op != UnaryOperatorType.PostDecrement)
                {
                    Write(JS.Types.SYSTEM_NULLABLE + ".");
                }
            }

            bool isAccessor = false;


            if (argResolverResult is MemberResolveResult memberArgResolverResult)
            {
                if (memberArgResolverResult.Member is IProperty prop)
                {
                    var isIgnore   = memberArgResolverResult.Member.DeclaringTypeDefinition != null && Emitter.Validator.IsExternalType(memberArgResolverResult.Member.DeclaringTypeDefinition);
                    var inlineAttr = prop.Getter != null?Emitter.GetAttribute(prop.Getter.Attributes, Translator.H5_ASSEMBLY + ".TemplateAttribute") : null;

                    var ignoreAccessor     = prop.Getter != null && Emitter.Validator.IsExternalType(prop.Getter);
                    var isAccessorsIndexer = Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member);

                    isAccessor = prop.IsIndexer;

                    if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer)
                    {
                        isAccessor = false;
                    }
                }
            }
            else if (argResolverResult is ArrayAccessResolveResult)
            {
                isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1;
            }

            Emitter.UnaryOperatorType = op;

            if ((isAccessor) &&
                (op == UnaryOperatorType.Increment ||
                 op == UnaryOperatorType.Decrement ||
                 op == UnaryOperatorType.PostIncrement ||
                 op == UnaryOperatorType.PostDecrement))
            {
                Emitter.IsUnaryAccessor = true;

                if (nullable)
                {
                    Write(JS.Funcs.H5_HASVALUE);
                    WriteOpenParentheses();
                    Emitter.IsUnaryAccessor = false;
                    unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    Write(") ? ");
                    Emitter.IsUnaryAccessor = true;
                    unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    Write(" : null)");
                }
                else
                {
                    unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                }

                Emitter.IsUnaryAccessor = oldAccessor;

                if (Emitter.Writers.Count > count)
                {
                    PopWriter();
                }
            }
            else
            {
                switch (op)
                {
                case UnaryOperatorType.BitNot:
                    if (nullable)
                    {
                        Write("bnot(");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(")");
                    }
                    else
                    {
                        Write("~");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Decrement:
                    if (nullable)
                    {
                        Write(JS.Funcs.H5_HASVALUE);
                        WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(") ? ");
                        Write("--");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(" : null)");
                    }
                    else
                    {
                        Write("--");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Increment:
                    if (nullable)
                    {
                        Write(JS.Funcs.H5_HASVALUE);
                        WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(") ? ");
                        Write("++");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(" : null)");
                    }
                    else
                    {
                        Write("++");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Minus:
                    if (nullable)
                    {
                        Write("neg(");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(")");
                    }
                    else
                    {
                        Write("-");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Not:
                    if (nullable)
                    {
                        Write("not(");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(")");
                    }
                    else
                    {
                        Write("!");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Plus:
                    if (nullable)
                    {
                        Write("pos(");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(")");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }

                    break;

                case UnaryOperatorType.PostDecrement:
                    if (nullable)
                    {
                        Write(JS.Funcs.H5_HASVALUE);
                        WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write("--");
                        Write(" : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write("--");
                    }
                    break;

                case UnaryOperatorType.PostIncrement:
                    if (nullable)
                    {
                        Write(JS.Funcs.H5_HASVALUE);
                        WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write("++");
                        Write(" : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write("++");
                    }
                    break;

                case UnaryOperatorType.Await:
                    if (Emitter.ReplaceAwaiterByVar)
                    {
                        var index = Array.IndexOf(Emitter.AsyncBlock.AwaitExpressions, unaryOperatorExpression.Expression) + 1;
                        Write(JS.Vars.ASYNC_TASK_RESULT + index);
                    }
                    else
                    {
                        var oldValue = Emitter.ReplaceAwaiterByVar;
                        var oldAsyncExpressionHandling = Emitter.AsyncExpressionHandling;

                        if (Emitter.IsAsync && !Emitter.AsyncExpressionHandling)
                        {
                            WriteAwaiters(unaryOperatorExpression.Expression);
                            Emitter.ReplaceAwaiterByVar     = true;
                            Emitter.AsyncExpressionHandling = true;
                        }

                        WriteAwaiter(unaryOperatorExpression.Expression);

                        Emitter.ReplaceAwaiterByVar     = oldValue;
                        Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;
                    }
                    break;

                default:
                    throw new EmitterException(unaryOperatorExpression, "Unsupported unary operator: " + unaryOperatorExpression.Operator.ToString());
                }

                if (Emitter.Writers.Count > count)
                {
                    PopWriter();
                }
            }

            Emitter.UnaryOperatorType = oldType;
        }