예제 #1
0
 public EmitterContext(SemanticModel semanticModel)
 {
     this.SemanticModel        = semanticModel;
     this.DataFlowAnalyzer     = new(semanticModel);
     this.VariablesToInline    = InlineDependencyVisitor.GetVariablesToInline(semanticModel);
     this.ResourceDependencies = ResourceDependencyVisitor.GetResourceDependencies(semanticModel);
 }
예제 #2
0
 public EmitterContext(SemanticModel semanticModel, EmitterSettings settings)
 {
     Settings             = settings;
     SemanticModel        = semanticModel;
     DataFlowAnalyzer     = new(semanticModel);
     VariablesToInline    = InlineDependencyVisitor.GetVariablesToInline(semanticModel);
     ResourceDependencies = ResourceDependencyVisitor.GetResourceDependencies(semanticModel);
     FunctionVariables    = FunctionVariableGeneratorVisitor.GetFunctionVariables(semanticModel).ToImmutableDictionary();
 }
예제 #3
0
        public static ImmutableHashSet <VariableSymbol> GetVariablesToInline(SemanticModel.SemanticModel model)
        {
            var visitor = new InlineDependencyVisitor(model);

            visitor.Visit(model.Root.Syntax);

            return(visitor.shouldInlineCache
                   .Where(kvp => kvp.Value)
                   .Select(kvp => kvp.Key)
                   .ToImmutableHashSet());
        }
예제 #4
0
        /// <summary>
        /// Checks if the specified variable needs to be inlined due to runtime limitations. In cases where the inlining is caused by accessing a variable that must be inlined,
        /// the variable access chain is returned. Otherwise, an empty chain is returned.
        /// </summary>
        /// <param name="model">The semantic model</param>
        /// <param name="variable">The variable to check</param>
        /// <param name="variableAccessChain">The variable access chain that leads to inlining or empty if not available.</param>
        public static bool ShouldInlineVariable(SemanticModel model, VariableDeclarationSyntax variable, out ImmutableArray <string> variableAccessChain)
        {
            variableAccessChain = ImmutableArray <string> .Empty;
            if (model.GetSymbolInfo(variable) is not VariableSymbol variableSymbol)
            {
                // we have errors - assume this is not meant to be inlined
                return(false);
            }

            var visitor = new InlineDependencyVisitor(model, variable);

            visitor.Visit(variable);

            if (!visitor.shouldInlineCache.TryGetValue(variableSymbol, out var shouldInline) || shouldInline != Decision.Inline)
            {
                return(false);
            }

            variableAccessChain = visitor.capturedSequence?.Reverse().ToImmutableArray() ?? ImmutableArray <string> .Empty;
            return(true);
        }
예제 #5
0
        public override void VisitForSyntax(ForSyntax syntax)
        {
            // save previous property loop count on the call stack
            var previousPropertyLoopCount = this.propertyLoopCount;

            switch (this.IsLoopAllowedHere(syntax))
            {
            case false:
                // this loop was used incorrectly
                this.diagnosticWriter.Write(DiagnosticBuilder.ForPosition(syntax.ForKeyword).ForExpressionsNotSupportedHere());
                break;

            case true when this.activeLoopCapableTopLevelDeclaration is VariableDeclarationSyntax variable && InlineDependencyVisitor.ShouldInlineVariable(this.semanticModel, variable, out var variableChain):
                // this is a loop variable that has a dependency on functions that are not supported in JSON variables
                // we are initially blocking this because not all cases can be generated in the JSON

                // unable to get a detailed variable dependency chain
                // log a generic error instead and put it on the "for" keyword
                this.diagnosticWriter.Write(DiagnosticBuilder.ForPosition(syntax.ForKeyword).VariableLoopsRuntimeDependencyNotAllowed(variableChain));

                break;

            case null:
                // this is a property loop
                this.propertyLoopCount += 1;

                if (this.propertyLoopCount > MaximumNestedPropertyLoopCount)
                {
                    // too many property loops
                    this.diagnosticWriter.Write(DiagnosticBuilder.ForPosition(syntax.ForKeyword).TooManyPropertyForExpressions());
                }

                break;
            }

            // visit children
            base.VisitForSyntax(syntax);

            // restore previous property loop count
            this.propertyLoopCount = previousPropertyLoopCount;
        }