Beispiel #1
0
        private SemanticModel GetSemanticModelInternal(SyntaxTree syntaxTree)
        {
            var builtinNamespaces =
                new NamespaceSymbol[] { new SystemNamespaceSymbol(), new AzNamespaceSymbol() }
            .ToImmutableDictionary(property => property.Name, property => property, LanguageConstants.IdentifierComparer);

            var bindings       = new Dictionary <SyntaxBase, Symbol>();
            var cyclesBySymbol = new Dictionary <DeclaredSymbol, ImmutableArray <DeclaredSymbol> >();

            var hierarchy = new SyntaxHierarchy();

            hierarchy.AddRoot(syntaxTree.ProgramSyntax);

            // create this in locked mode by default
            // this blocks accidental type or binding queries until binding is done
            // (if a type check is done too early, unbound symbol references would cause incorrect type check results)
            var symbolContext = new SymbolContext(new TypeManager(resourceTypeProvider, bindings, cyclesBySymbol, hierarchy), bindings, this);

            // collect declarations
            var declarations       = new List <DeclaredSymbol>();
            var declarationVisitor = new DeclarationVisitor(symbolContext, declarations);

            declarationVisitor.Visit(syntaxTree.ProgramSyntax);

            // in cases of duplicate declarations we will see multiple declaration symbols in the result list
            // for simplicitly we will bind to the first one
            // it may cause follow-on type errors, but there will also be errors about duplicate identifiers as well
            var uniqueDeclarations = declarations
                                     .ToLookup(x => x.Name, LanguageConstants.IdentifierComparer)
                                     .ToImmutableDictionary(x => x.Key, x => x.First(), LanguageConstants.IdentifierComparer);

            // bind identifiers to declarations
            var binder = new NameBindingVisitor(uniqueDeclarations, bindings, builtinNamespaces);

            binder.Visit(syntaxTree.ProgramSyntax);

            var shortestCycleBySymbol = CyclicCheckVisitor.FindCycles(syntaxTree.ProgramSyntax, uniqueDeclarations, bindings);

            foreach (var kvp in shortestCycleBySymbol)
            {
                cyclesBySymbol.Add(kvp.Key, kvp.Value);
            }

            // TODO: Avoid looping 5 times?
            var file = new FileSymbol(
                syntaxTree.FilePath,
                syntaxTree.ProgramSyntax,
                builtinNamespaces,
                declarations.OfType <ParameterSymbol>(),
                declarations.OfType <VariableSymbol>(),
                declarations.OfType <ResourceSymbol>(),
                declarations.OfType <ModuleSymbol>(),
                declarations.OfType <OutputSymbol>());

            // name binding is done
            // allow type queries now
            symbolContext.Unlock();

            return(new SemanticModel(file, symbolContext.TypeManager, bindings));
        }
Beispiel #2
0
        public static bool IsCycled(IASTNode node)
        {
            CyclicCheckVisitor vis = new CyclicCheckVisitor();

            try
            {
                vis.VisitNode(node);
            }
            catch (Exception)
            {
                return(false);
            }

            return(true);
        }
Beispiel #3
0
 private static ImmutableDictionary <DeclaredSymbol, ImmutableArray <DeclaredSymbol> > GetCyclesBySymbol(SyntaxTree syntaxTree, IReadOnlyDictionary <string, DeclaredSymbol> uniqueDeclarations, IReadOnlyDictionary <SyntaxBase, Symbol> bindings)
 {
     return(CyclicCheckVisitor.FindCycles(syntaxTree.ProgramSyntax, uniqueDeclarations, bindings));
 }
Beispiel #4
0
 private static ImmutableDictionary <DeclaredSymbol, ImmutableArray <DeclaredSymbol> > GetCyclesBySymbol(BicepFile bicepFile, IReadOnlyDictionary <SyntaxBase, Symbol> bindings)
 {
     return(CyclicCheckVisitor.FindCycles(bicepFile.ProgramSyntax, bindings));
 }