Esempio n. 1
0
        public void GenerateInto(Scope scope)
        {
            var hasReturn = SyntaxUtil.HasReturnStatement(Body);

            if (scope.IsInStatementContext)
            {
                if (hasReturn == false)
                {
                    SyntaxUtil.CreateReturnStatement(this.returnType, Body, scope.StatementContext.TryCreateResultStatement);
                }

                foreach (var b in Body)
                {
                    scope.StatementContext.AddStatement(b);
                }
            }
            else
            {
                if (hasReturn == false)
                {
                    SyntaxUtil.CreateReturnStatement(this.returnType, Body, (ExpressionSyntax e, out StatementSyntax s) => {
                        s = SyntaxFactory.ReturnStatement(e)
                            .WithAdditionalAnnotations(ScriptGenAnnotations.ResultStatement);
                        return(true);
                    });
                }

                scope.Context.AddExpression(
                    SyntaxUtil.CreateImmediatelyInvokedFunction(returnType, Body));
            }
        }
Esempio n. 2
0
        private SyntaxNode ProcessNamespace(SyntaxNode syntaxRoot)
        {
            var firstNamespace = syntaxRoot.DescendantNodesAndSelf().OfType <NamespaceDeclarationSyntax>().FirstOrDefault();

            if (firstNamespace == null)
            {
                return(syntaxRoot);
            }

            var list = firstNamespace.GetLeadingTrivia();

            if (list.Count == 0)
            {
                var newLine = SyntaxUtil.GetBestNewLineTrivia(firstNamespace);
                list = list.Add(newLine);
                return(syntaxRoot.ReplaceNode(firstNamespace, firstNamespace.WithLeadingTrivia(list)));
            }
            else if (list.Count == 1 && list[0].IsKind(SyntaxKind.EndOfLineTrivia))
            {
                // The namespace node is typically preceeded by a using node.  In thate case the trivia will
                // be split between the two nodes.  If the namespace already has a newline leading trivia then
                // there is at least a single blank between the nodes as the using will have a trailing new
                // line as well (in case of a single on it will be on the using).
                return(syntaxRoot);
            }
            else
            {
                return(ProcessCore(syntaxRoot, firstNamespace));
            }
        }
        private static SyntaxToken FixCloseBraceLeadingTrivia(SyntaxToken token)
        {
            if (!token.HasLeadingTrivia)
            {
                return(token);
            }

            var triviaList = token.LeadingTrivia;

            if (triviaList.All(x => x.IsKind(SyntaxKind.WhitespaceTrivia) || x.IsKind(SyntaxKind.EndOfLineTrivia)))
            {
                // Simplest case.  It's all new lines and white space.
                if (EndsWithSimpleNewLine(token.GetPreviousToken().TrailingTrivia))
                {
                    triviaList = SyntaxTriviaList.Empty;
                }
                else
                {
                    // new line and we are done.
                    triviaList = SyntaxFactory.TriviaList(SyntaxUtil.GetBestNewLineTrivia(token));
                }
            }
            else
            {
                triviaList = RemoveNewLinesFromTop(triviaList);
                triviaList = RemoveNewLinesFromBottom(triviaList);
            }

            return(token.WithLeadingTrivia(triviaList));
        }
Esempio n. 4
0
        public FieldGetContext(ScenarioTag scenario, ScenarioTag.ScriptSyntaxNode node, MemberNameRepository nameRepo) : base(node)
        {
            this.OwnDataType = node.DataType;

            if (node.NodeString == 0)
            {
                accessor = SyntaxFactory.DefaultExpression(SyntaxUtil.ScriptTypeSyntax(node.DataType));
            }
            else
            {
                var stringVal = SyntaxUtil.GetScriptString(scenario, node);

                if (stringVal == "none")
                {
                    accessor = SyntaxFactory.DefaultExpression(SyntaxUtil.ScriptTypeSyntax(node.DataType));
                }
                else
                {
                    if (nameRepo.TryGetName(stringVal, node.DataType.ToString(), node.NodeData_H16, out var finalName))
                    {
                        accessor = SyntaxFactory.IdentifierName(finalName);
                    }
                    else
                    {
                        accessor = SyntaxFactory.IdentifierName(SyntaxUtil.SanitizeIdentifier(stringVal));
                    }
                }
            }

            accessor = accessor.WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(node.DataType));
        }
        /// <summary>
        /// Get the new leading trivia list that will add the double blank line that we are looking
        /// for.
        /// </summary>
        private bool TryGetNewLeadingTrivia(SyntaxNode node, out SyntaxTriviaList newTriviaList)
        {
            var newLineTrivia = SyntaxUtil.GetBestNewLineTrivia(node);
            var list          = node.GetLeadingTrivia();
            var index         = list.Count - 1;

            MoveBackwardsPastWhitespace(list, ref index);
            if (index < 0 || !list[index].IsAnyEndOfLine())
            {
                // There is no newline before the using at all.  Add a double newline to
                // get the blank we are looking for
                newTriviaList = list.InsertRange(index + 1, new[] { newLineTrivia, newLineTrivia });
                return(true);
            }

            var wasDirective = list[index].IsDirective;

            index--;

            // Move past any directives that are above the token.  The newline needs to
            // be above them.
            while (index >= 0 && list[index].IsDirective)
            {
                index--;
            }

            if (wasDirective)
            {
                // There was a directive above the using and index now points directly before
                // that.  This token must be a new line.
                if (index < 0 || !list[index].IsKind(SyntaxKind.EndOfLineTrivia))
                {
                    newTriviaList = list.Insert(index + 1, newLineTrivia);
                    return(true);
                }

                index--;
            }

            // In the logical line above the using.  Need to see <blank><eol> in order for the
            // using to be correct
            var insertIndex = index + 1;

            MoveBackwardsPastWhitespace(list, ref index);
            if (index < 0 || !list[index].IsAnyEndOfLine())
            {
                // If this is the first item in the file then there is no need for a double
                // blank line.
                if (index >= 0 || node.FullSpan.Start != 0)
                {
                    newTriviaList = list.Insert(insertIndex, newLineTrivia);
                    return(true);
                }
            }

            // The using is well formed so there is no work to be done.
            newTriviaList = SyntaxTriviaList.Empty;
            return(false);
        }
Esempio n. 6
0
        public VariableAccessContext(ScenarioTag tag, ScenarioTag.ScriptSyntaxNode node) : base(node)
        {
            this.OwnDataType = node.DataType;

            access = SyntaxFactory.MemberAccessExpression(
                SyntaxKind.SimpleMemberAccessExpression,
                SyntaxFactory.ThisExpression(),
                SyntaxFactory.IdentifierName(
                    SyntaxUtil.SanitizeIdentifier(
                        SyntaxUtil.GetScriptString(tag, node))))
                     .WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(node.DataType));
        }
Esempio n. 7
0
        public ScriptInvocationContext(ScenarioTag scenario, ScenarioTag.ScriptSyntaxNode node) : base(node)
        {
            var method = scenario.ScriptMethods[node.OperationId];

            invocation = SyntaxFactory.InvocationExpression(
                SyntaxFactory.MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    SyntaxFactory.ThisExpression(),
                    SyntaxFactory.IdentifierName(
                        SyntaxUtil.SanitizeIdentifier(method.Description))))
                         .WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(method.ReturnType));
        }
Esempio n. 8
0
        public TagGetContext(ScenarioTag scenario, ScenarioTag.ScriptSyntaxNode node) : base(node)
        {
            this.OwnDataType = node.DataType;

            invocation = InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                     IdentifierName("Engine"),
                                                                     GenericName(Identifier(nameof(IScriptEngine.GetTag)))
                                                                     .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(
                                                                                                                SyntaxUtil.ScriptTypeSyntax(this.OwnDataType.Value))))))
                         .AddArgumentListArguments(
                Argument(SyntaxUtil.LiteralExpression(SyntaxUtil.GetScriptString(scenario, node))),
                Argument(SyntaxUtil.LiteralExpression(node.NodeData_32)))
                         .WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(node.DataType));
        }
Esempio n. 9
0
        public LiteralContext(ScenarioTag scenario, ScenarioTag.ScriptSyntaxNode node, Scope containing) : base(node)
        {
            this.OwnDataType = node.DataType;

            var dest = node.DataType;

            if (SyntaxUtil.NumericLiteralTypes.Contains(node.DataType) &&
                containing.Context is BinaryOperatorContext bin &&
                SyntaxUtil.NumericLiteralTypes.Contains(bin.OwnDataType.Value))
            {
                dest = bin.OwnDataType.Value;
            }

            this.literal = SyntaxUtil.LiteralExpression(scenario, node, dest);
        }
Esempio n. 10
0
        public MethodCallContext AddArgument(ExpressionSyntax argument)
        {
            arguments.Add(SyntaxFactory.Argument(argument));

            if (SyntaxUtil.TryGetTypeOfExpression(argument, out var t))
            {
                argumentTypes.Add(t);
            }
            else
            {
                throw new System.Exception("Couldn't determine argument type");
            }

            return(this);
        }
Esempio n. 11
0
        SyntaxNode AddNewLineToEndOfFileTokenLeadingTriviaIfNecessary(SyntaxNode syntaxRoot, SyntaxToken endofFileToken)
        {
            if (endofFileToken.LeadingTrivia.Last().IsKind(SyntaxKind.EndOfLineTrivia))
            {
                return(syntaxRoot);
            }

            var newLine      = SyntaxUtil.GetBestNewLineTriviaRecursive(endofFileToken.Parent);
            var newLastToken = endofFileToken.WithTrailingTrivia(endofFileToken.TrailingTrivia.Concat(new[] { newLine }));

            return(syntaxRoot.ReplaceToken(endofFileToken, newLastToken));


            return(syntaxRoot);
        }
Esempio n. 12
0
        /// <summary>
        /// Remove all extra new lines from the begining of a close brace token.  This is only called in
        /// the case at least one new line is present hence we don't have to worry about the single line
        /// case.
        /// </summary>
        private static SyntaxTriviaList RemoveNewLinesFromBottom(SyntaxTriviaList triviaList)
        {
            var index     = triviaList.Count - 1;
            var searching = true;

            while (index >= 0 && searching)
            {
                var current = triviaList[index];
                switch (current.Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                case SyntaxKind.EndOfLineTrivia:
                    index--;
                    break;

                default:
                    searching = false;
                    break;
                }
            }

            // Nothing to adjust, the removal of new lines from the top of the list will handle all of the
            // important cases.
            if (index < 0)
            {
                return(triviaList);
            }

            var list = new List <SyntaxTrivia>(triviaList.Count);

            for (int i = 0; i <= index; i++)
            {
                list.Add(triviaList[i]);
            }

            // A directive has an implicit new line after it.
            if (!list[index].IsDirective)
            {
                list.Add(SyntaxUtil.GetBestNewLineTrivia(triviaList));
            }

            if (triviaList.Last().IsKind(SyntaxKind.WhitespaceTrivia))
            {
                list.Add(triviaList.Last());
            }

            return(SyntaxFactory.TriviaList(list));
        }
Esempio n. 13
0
        public UnknownContext(ScenarioTag scenario, ScenarioTag.ScriptSyntaxNode node) : base(node)
        {
            this.OwnDataType = node.DataType;

            string unknownDescription = "";

            if (node.NodeString > 0 && node.NodeString < scenario.ScriptStrings.Length &&
                scenario.ScriptStrings[node.NodeString - 1] == 0)
            {
                unknownDescription = SyntaxUtil.GetScriptString(scenario, node);
            }

            unknownDescription += $" -{node.NodeType}<{node.DataType}>";
            invocation          = SyntaxFactory.InvocationExpression(
                SyntaxFactory.IdentifierName("UNKNOWN"),
                SyntaxFactory.ArgumentList(
                    SyntaxFactory.SingletonSeparatedList(
                        SyntaxFactory.Argument(SyntaxUtil.LiteralExpression(unknownDescription)))));
        }
Esempio n. 14
0
        public SyntaxNode Process(SyntaxNode syntaxRoot, string languageName)
        {
            bool needsNewLine;
            var  endOfFileToken = syntaxRoot.GetLastToken(true, true, true, true);

            if (!endOfFileToken.IsKind(SyntaxKind.EndOfFileToken))
            {
                throw new InvalidOperationException("Expected last token to be EndOfFileToken, was actually: " + endOfFileToken.Kind());
            }

            if (endOfFileToken.HasLeadingTrivia)
            {
                return(AddNewLineToEndOfFileTokenLeadingTriviaIfNecessary(syntaxRoot, endOfFileToken));
            }

            var lastToken = syntaxRoot.GetLastToken();

            if (!lastToken.HasTrailingTrivia)
            {
                needsNewLine = true;
            }
            else
            {
                var lastTrivia = lastToken.TrailingTrivia.Last();
                if (lastTrivia.IsKind(SyntaxKind.EndOfLineTrivia))
                {
                    needsNewLine = false;
                }
                else
                {
                    needsNewLine = true;
                }
            }

            if (needsNewLine)
            {
                var newLine      = SyntaxUtil.GetBestNewLineTriviaRecursive(lastToken.Parent);
                var newLastToken = lastToken.WithTrailingTrivia(lastToken.TrailingTrivia.Concat(new[] { newLine }));
                return(syntaxRoot.ReplaceToken(lastToken, newLastToken));
            }
            return(syntaxRoot);
        }
Esempio n. 15
0
        public void GenerateInto(Scope scope)
        {
            Debug.Assert(operands.Count >= 2, "Not enough operands for binary expression");

            var ops = new Queue <ExpressionSyntax>();

            foreach (var op in operands)
            {
                ops.Enqueue(op);
            }

            var            left    = ops.Dequeue();
            ScriptDataType?topType = this.OwnDataType;

            while (ops.Any())
            {
                var right = ops.Dequeue();

                var binExp = SyntaxFactory.BinaryExpression(operatorSyntaxKind,
                                                            left, right);

                if (numericPromotionOperators.Contains(this.operatorSyntaxKind) &&
                    SyntaxUtil.TryGetTypeOfExpression(left, out var leftType) &&
                    SyntaxUtil.TryGetTypeOfExpression(right, out var rightType))
                {
                    var promoted = SyntaxUtil.BinaryNumericPromotion(leftType, rightType);
                    binExp  = binExp.WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(promoted));
                    topType = promoted;
                }

                left = binExp;
            }

            if (topType.HasValue && topType.Value != scope.Type)
            {
                left = SyntaxUtil.CreateCast(topType.Value, scope.Type, SyntaxFactory.ParenthesizedExpression(left));
            }

            scope.Context.AddExpression(left);
        }
Esempio n. 16
0
        /// <summary>
        /// Don't allow consecutive newlines at the top of the comments / pragma before a close
        /// brace token.
        /// </summary>
        private static SyntaxTriviaList RemoveNewLinesFromTop(SyntaxTriviaList triviaList)
        {
            // This rule only needs to run if there is a new line at the top.
            if (!IsSimpleNewLine(triviaList, 0))
            {
                return(triviaList);
            }

            var list = new List <SyntaxTrivia>(triviaList.Count);

            list.Add(SyntaxUtil.GetBestNewLineTrivia(triviaList));

            var index = MovePastSimpleNewLines(triviaList, 0);

            while (index < triviaList.Count)
            {
                list.Add(triviaList[index]);
                index++;
            }

            return(SyntaxFactory.TriviaList(list));
        }
Esempio n. 17
0
        public IStatementContext AddStatement(StatementSyntax statement)
        {
            if (statement is ExpressionStatementSyntax exp)
            {
                subexpressions.Add(exp.Expression);
            }
            else
            {
                var returnType = ScriptDataType.Void;

                var annotations = statement.GetAnnotations(ScriptGenAnnotations.TypeAnnotationKind);

                if (annotations.Any())
                {
                    returnType = (ScriptDataType)int.Parse(annotations.First().Data);
                }

                subexpressions.Add(SyntaxUtil.CreateImmediatelyInvokedFunction(returnType, new[] { statement }));
            }

            return(this);
        }
Esempio n. 18
0
        /// <summary>
        /// Get the new leading trivia list that will add the double blank line that we are looking
        /// for.
        /// </summary>
        private SyntaxTriviaList GetNewLeadingTrivia(SyntaxNode node)
        {
            var list          = node.GetLeadingTrivia();
            var searchIndex   = 0;
            var newLineTrivia = SyntaxUtil.GetBestNewLineTrivia(node);
            var prev          = node.FindPreviousNodeInParent();

            if (prev == null)
            {
                if (node.Span.Start == 0)
                {
                    // First item in the file.  Do nothing for this case.
                    return(list);
                }
            }
            else
            {
                // If there is no new line in the trailing trivia of the previous node then need to add
                // one to put this node on the next line.
                if (prev.GetTrailingTrivia().Count == 0 || !prev.GetTrailingTrivia().Last().IsAnyEndOfLine())
                {
                    list        = list.Insert(0, newLineTrivia);
                    searchIndex = 1;
                }
            }

            // Ensure there are blank above #pragma directives here.  This is an attempt to maintain compatibility
            // with the original design of this rule which had special spacing rules for #pragma.  No reason
            // was given for the special casing, only tests.
            if (searchIndex < list.Count && list[0].IsKind(SyntaxKind.PragmaWarningDirectiveTrivia) && list[0].FullSpan.Start != 0)
            {
                list = list.Insert(searchIndex, newLineTrivia);
                searchIndex++;
            }

            EnsureHasBlankLineAtEnd(ref list, searchIndex, newLineTrivia);

            return(list);
        }
Esempio n. 19
0
        public EntityGetContext(ScenarioTag scenario, ScenarioTag.ScriptSyntaxNode node, MemberNameRepository nameRepo) : base(node)
        {
            this.OwnDataType = node.DataType;

            if (node.NodeString == 0)
            {
                accessor = SyntaxFactory.DefaultExpression(SyntaxUtil.ScriptTypeSyntax(node.DataType));
            }
            else
            {
                var stringVal = SyntaxUtil.GetScriptString(scenario, node);

                if (stringVal == "none")
                {
                    accessor = SyntaxFactory.DefaultExpression(SyntaxUtil.ScriptTypeSyntax(node.DataType));
                }
                else
                {
                    if (nameRepo.TryGetName(stringVal, nameof(ScenarioTag.EntityReference), node.NodeData_H16, out var finalName))
                    {
                        accessor = SyntaxFactory.IdentifierName(finalName);
                    }
                    else
                    {
                        accessor = SyntaxFactory.IdentifierName(SyntaxUtil.SanitizeIdentifier(stringVal));
                    }

                    if (node.DataType != ScriptDataType.EntityIdentifier)
                    {
                        accessor = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                        accessor,
                                                                        SyntaxFactory.IdentifierName(nameof(ScenarioEntity <object> .Entity)));
                    }
                }
            }

            accessor = accessor.WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(node.DataType));
        }
Esempio n. 20
0
        public void GenerateInto(Scope scope)
        {
            var invocationExpression = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                            SyntaxFactory.IdentifierName("Engine"),
                                                                            SyntaxFactory.IdentifierName(this.MethodName));

            ExpressionSyntax invocation = SyntaxFactory.InvocationExpression(invocationExpression)
                                          .WithArgumentList(SyntaxFactory.ArgumentList(
                                                                SyntaxFactory.SeparatedList(this.arguments)))
                                          .WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(this.ReturnType));

            var tempArgs = new List <Type>();

            foreach (var t in argumentTypes)
            {
                if (t.HasValue && SyntaxUtil.TryGetTypeFromScriptType(t.Value, out var T))
                {
                    tempArgs.Add(T);
                }
                else
                {
                    break;
                }
            }

            if (tempArgs.Count == argumentTypes.Count)
            {
                // Do full overload match
                var method = typeof(IScriptEngine).GetMethod(this.MethodName,
                                                             BindingFlags.Public | BindingFlags.Instance,
                                                             null,
                                                             tempArgs.ToArray(),
                                                             null);

                if (method != null)
                {
                    SyntaxUtil.AwaitIfNeeded(method, ref invocation, out var materializedReturnType);

                    if (SyntaxUtil.TryGetScriptTypeFromType(materializedReturnType, out var fromType))
                    {
                        // Insert cast to destination
                        invocation = SyntaxUtil.CreateCast(fromType, this.ReturnType, invocation)
                                     .WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(this.ReturnType));
                    }
                }
            }
            else
            {
                // Fallback to name only lookup
                var scriptEngineMethods = typeof(IScriptEngine).GetMethods().Where(m => m.Name == this.MethodName);

                if (scriptEngineMethods.Any())
                {
                    //var hasOverload = scriptEngineMethods.Any(m => m.ReturnType == destinationType);

                    //if (hasOverload == false)
                    {
                        var method = scriptEngineMethods.First();

                        SyntaxUtil.AwaitIfNeeded(method, ref invocation, out var materializedReturnType);

                        if (SyntaxUtil.TryGetScriptTypeFromType(materializedReturnType, out var fromType) && fromType != this.ReturnType)
                        {
                            // Insert cast to destination
                            invocation = SyntaxUtil.CreateCast(fromType, this.ReturnType, invocation)
                                         .WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(this.ReturnType));
                        }
                    }
                }
            }

            scope.Context.AddExpression(invocation);
        }
Esempio n. 21
0
        public AiGetContext(ScenarioTag scenario, ScenarioTag.ScriptSyntaxNode node, MemberNameRepository nameRepo) : base(node)
        {
            this.OwnDataType = node.DataType;

            if (node.NodeString == 0)
            {
                accessor = SyntaxFactory.DefaultExpression(SyntaxUtil.ScriptTypeSyntax(node.DataType));
            }
            else
            {
                var stringVal = SyntaxUtil.GetScriptString(scenario, node);

                var slashIndex = stringVal.IndexOf('/');

                if (slashIndex > 0)
                {
                    Debug.Assert(node.NodeData_B0 == 192);

                    // It's a squad member accessor
                    var squadName  = stringVal.Substring(0, slashIndex);
                    var memberName = stringVal.Substring(slashIndex + 1);

                    if (nameRepo.TryGetName(squadName, node.DataType.ToString(), node.NodeData_B1, out var finalSquad) &&
                        nameRepo.NestedRepos.TryGetValue(finalSquad, out var nestedRepo) &&
                        nestedRepo.TryGetName(memberName, node.DataType.ToString(), node.NodeData_H16, out var finalProp))
                    {
                        accessor = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                        SyntaxFactory.IdentifierName(SyntaxUtil.SanitizeIdentifier(finalSquad)),
                                                                        SyntaxFactory.IdentifierName(SyntaxUtil.SanitizeIdentifier(finalProp)));
                    }
                    else
                    {
                        accessor = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                        SyntaxFactory.IdentifierName(SyntaxUtil.SanitizeIdentifier(squadName)),
                                                                        SyntaxFactory.IdentifierName(SyntaxUtil.SanitizeIdentifier(memberName)));
                    }
                }
                else
                {
                    // Ambiguous reference to either a squad or squad group...?
                    if (nameRepo.TryGetName(stringVal, node.DataType.ToString(), node.NodeData_H16, out var finalSquad))
                    {
                        if (nameRepo.NestedRepos.TryGetValue(finalSquad, out var nestedRepo))
                        {
                            accessor = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                            SyntaxFactory.IdentifierName(SyntaxUtil.SanitizeIdentifier(finalSquad)),
                                                                            SyntaxFactory.IdentifierName(SyntaxUtil.SanitizeIdentifier("Squad")));
                        }
                        else
                        {
                            accessor = SyntaxFactory.IdentifierName(finalSquad);
                        }
                    }
                    else
                    {
                        accessor = SyntaxFactory.IdentifierName(SyntaxUtil.SanitizeIdentifier(stringVal));
                    }
                }
            }

            accessor = accessor.WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(node.DataType));
        }
Esempio n. 22
0
        public void GenerateInto(Scope scope)
        {
            Debug.Assert(scope == this.containingScope, "Generating into an unexpected scope");
            Debug.Assert(this.condition != null, "Condition expression was not provided");
            Debug.Assert(whenTrueStatements.Any(), "WhenTrue was not provided");

            var generatedStatements = new List <StatementSyntax>();

            if (this.producesValue)
            {
                var resultType = SyntaxUtil.ScriptTypeSyntax(this.containingScope.Type);

                // Ensure that if a value must be produced, we have an else with default value
                if (whenFalseStatements.Any() == false)
                {
                    whenFalseStatements.Add(ExpressionStatement(DefaultExpression(resultType)));
                }

                if (this.shouldHoist)
                {
                    var initialization = DefaultExpression(resultType);

                    generatedStatements.Add(LocalDeclarationStatement(VariableDeclaration(resultType)
                                                                      .WithVariables(SingletonSeparatedList(
                                                                                         VariableDeclarator(resultVariable.Identifier)
                                                                                         .WithInitializer(
                                                                                             EqualsValueClause(initialization)))))
                                            .WithAdditionalAnnotations(ScriptGenAnnotations.HoistedResultVar));

                    if (HasResultVarAssignment(whenTrueStatements) == false)
                    {
                        InsertResultVarAssignment(whenTrueStatements);
                    }

                    if (whenFalseStatements.Any() && HasResultVarAssignment(whenFalseStatements) == false)
                    {
                        InsertResultVarAssignment(whenFalseStatements);
                    }
                }
                else
                {
                    if (SyntaxUtil.HasReturnStatement(whenTrueStatements) == false)
                    {
                        SyntaxUtil.CreateReturnStatement(this.containingScope.Type, whenTrueStatements, (ExpressionSyntax e, out StatementSyntax s) =>
                        {
                            s = ReturnStatement(e).WithAdditionalAnnotations(ScriptGenAnnotations.ResultStatement);
                            return(true);
                        });
                    }

                    if (SyntaxUtil.HasReturnStatement(whenFalseStatements) == false)
                    {
                        SyntaxUtil.CreateReturnStatement(this.containingScope.Type, whenFalseStatements, (ExpressionSyntax e, out StatementSyntax s) =>
                        {
                            s = ReturnStatement(e).WithAdditionalAnnotations(ScriptGenAnnotations.ResultStatement);
                            return(true);
                        });
                    }
                }
            }

            var trueBlock = Block(whenTrueStatements);

            var unreachable = this.condition.IsEquivalentTo(SyntaxUtil.LiteralExpression(true));

            if (unreachable == false && whenFalseStatements.Any())
            {
                StatementSyntax falseBlock = Block(whenFalseStatements);

                // Collapse if/else if/...
                if (whenFalseStatements.Count == 1 && whenFalseStatements[0] is IfStatementSyntax ifStatement)
                {
                    falseBlock = ifStatement;
                }

                generatedStatements.Add(
                    IfStatement(condition, trueBlock, ElseClause(falseBlock))
                    .WithLeadingTrivia(SyntaxFactory.Whitespace(Environment.NewLine))
                    .WithAdditionalAnnotations(ScriptGenAnnotations.IfStatement));
            }
            else
            {
                generatedStatements.Add(
                    IfStatement(condition, trueBlock)
                    .WithLeadingTrivia(SyntaxFactory.Whitespace(Environment.NewLine))
                    .WithAdditionalAnnotations(ScriptGenAnnotations.IfStatement));
            }

            if (this.shouldHoist == false && this.producesValue)
            {
                var last = generatedStatements.Last();

                generatedStatements.Remove(last);
                generatedStatements.Add(last.WithAdditionalAnnotations(ScriptGenAnnotations.ResultStatement));
            }

            if (scope.IsInStatementContext || this.shouldHoist)
            {
                // Insert statements into appropriate statement context
                foreach (var statement in generatedStatements)
                {
                    scope.StatementContext.AddStatement(statement);
                }

                if (this.shouldHoist)
                {
                    // Insert result var into place
                    scope.Context.AddExpression(this.resultVariable);
                }
            }
            else
            {
                // Insert IIFE into place
                scope.Context.AddExpression(SyntaxUtil.CreateImmediatelyInvokedFunction(scope.Type, generatedStatements));
            }
        }