public void EmptyHierarchy_GetParent_ShouldThrow() { var hierarchy = new SyntaxHierarchy(); Action fail = () => hierarchy.GetParent(TestSyntaxFactory.CreateNull()); fail.Should().Throw <ArgumentException>().WithMessage("Unable to determine parent of specified node of type 'NullLiteralSyntax' at span '[0:0]' because it has not been indexed."); }
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)); }
public BicepFile(Uri fileUri, ImmutableArray <int> lineStarts, ProgramSyntax programSyntax) { FileUri = fileUri; LineStarts = lineStarts; ProgramSyntax = programSyntax; Hierarchy = new SyntaxHierarchy(); Hierarchy.AddRoot(ProgramSyntax); }
public DeclaredTypeManager(SyntaxHierarchy hierarchy, ITypeManager typeManager, IResourceTypeProvider resourceTypeProvider, IReadOnlyDictionary <SyntaxBase, Symbol> bindings, IReadOnlyDictionary <DeclaredSymbol, ImmutableArray <DeclaredSymbol> > cyclesBySyntax, ResourceScopeType targetScope) { this.hierarchy = hierarchy; this.typeManager = typeManager; this.resourceTypeProvider = resourceTypeProvider; this.bindings = bindings; this.cyclesBySyntax = cyclesBySyntax; this.targetScope = targetScope; }
public void EmptyFile_GetProgramParent_ShouldReturnNull() { var hierarchy = new SyntaxHierarchy(); var program = SyntaxFactory.CreateFromText(string.Empty); hierarchy.AddRoot(program); hierarchy.GetParent(program).Should().BeNull(); }
public void EmptyFile_GetProgramParent_ShouldReturnNull() { var hierarchy = new SyntaxHierarchy(); var program = ParserHelper.Parse(string.Empty); hierarchy.AddRoot(program); hierarchy.GetParent(program).Should().BeNull(); }
public BicepFile(Uri fileUri, ImmutableArray <int> lineStarts, ProgramSyntax programSyntax) { FileUri = fileUri; LineStarts = lineStarts; ProgramSyntax = programSyntax; Hierarchy = new SyntaxHierarchy(); Hierarchy.AddRoot(ProgramSyntax); DisabledDiagnosticsCache = new DisabledDiagnosticsCache(ProgramSyntax, lineStarts); }
public void VariousObjects_ShouldProduceNoDiagnosticsWhenAssignedToObjectType(string displayName, ObjectSyntax @object) { var hierarchy = new SyntaxHierarchy(); hierarchy.AddRoot(@object); var(narrowedType, diagnostics) = NarrowTypeAndCollectDiagnostics(hierarchy, @object, LanguageConstants.Object); diagnostics.Should().BeEmpty(); }
public void Variousobjects_ShouldProduceAnErrorWhenAssignedToString(string displayName, ObjectSyntax @object) { var hierarchy = new SyntaxHierarchy(); hierarchy.AddRoot(@object); var(narrowedType, diagnostics) = NarrowTypeAndCollectDiagnostics(hierarchy, @object, LanguageConstants.Int); diagnostics.Should().HaveCount(1); diagnostics.Single().Message.Should().Be("Expected a value of type \"int\" but the provided value is of type \"object\"."); }
public void MinimalResourceShouldBeValid() { var obj = TestSyntaxFactory.CreateObject(new[] { TestSyntaxFactory.CreateProperty("name", TestSyntaxFactory.CreateString("test")) }); var hierarchy = new SyntaxHierarchy(); hierarchy.AddRoot(obj); var(_, diagnostics) = NarrowTypeAndCollectDiagnostics(hierarchy, obj, CreateDummyResourceType()); diagnostics.Should().BeEmpty(); }
public void NonEmtyFile_GetParent_ShouldReturnExpectedNode() { var hierarchy = new SyntaxHierarchy(); var program = SyntaxFactory.CreateFromText("param foo string\r\nvar bar = 42"); hierarchy.AddRoot(program); hierarchy.GetParent(program).Should().BeNull(); var nodes = SyntaxAggregator.Aggregate(program, new List <SyntaxBase>(), (accumulated, current) => { accumulated.Add(current); return(accumulated); }, accumulated => accumulated); var paramDecl = nodes.OfType <ParameterDeclarationSyntax>().Single(); hierarchy.GetParent(paramDecl).Should().BeSameAs(program); var varDecl = nodes.OfType <VariableDeclarationSyntax>().Single(); hierarchy.GetParent(varDecl).Should().BeSameAs(program); var newLine = nodes.OfType <Token>().Single(t => t.Type == TokenType.NewLine); hierarchy.GetParent(newLine).Should().BeSameAs(program); var paramIdSyntax = nodes.OfType <IdentifierSyntax>().Single(id => string.Equals(id.IdentifierName, "foo")); hierarchy.GetParent(paramIdSyntax).Should().BeSameAs(paramDecl); var varIdSyntax = nodes.OfType <IdentifierSyntax>().Single(id => string.Equals(id.IdentifierName, "bar")); hierarchy.GetParent(varIdSyntax).Should().BeSameAs(varDecl); var paramTypeSyntax = nodes.OfType <TypeSyntax>().Single(); hierarchy.GetParent(paramTypeSyntax).Should().BeSameAs(paramDecl); var paramTypeToken = nodes.OfType <Token>().Single(t => t.Type == TokenType.Identifier && string.Equals(t.Text, "string")); hierarchy.GetParent(paramTypeToken).Should().BeSameAs(paramTypeSyntax); }
public TypeAssignmentVisitor( IResourceTypeProvider resourceTypeProvider, TypeManager typeManager, IReadOnlyDictionary <SyntaxBase, Symbol> bindings, IReadOnlyDictionary <DeclaredSymbol, ImmutableArray <DeclaredSymbol> > cyclesBySymbol, SyntaxHierarchy hierarchy, ResourceScopeType targetScope) { this.resourceTypeProvider = resourceTypeProvider; this.typeManager = typeManager; // bindings will be modified by name binding after this object is created // so we can't make an immutable copy here // (using the IReadOnlyDictionary to prevent accidental mutation) this.bindings = bindings; this.cyclesBySymbol = cyclesBySymbol; this.assignedTypes = new Dictionary <SyntaxBase, TypeAssignment>(); this.hierarchy = hierarchy; this.targetScope = targetScope; }
public void ResourceWithValidZonesShouldBeAccepted() { var obj = TestSyntaxFactory.CreateObject(new[] { TestSyntaxFactory.CreateProperty("name", TestSyntaxFactory.CreateString("test")), TestSyntaxFactory.CreateProperty("zones", TestSyntaxFactory.CreateArray(new [] { TestSyntaxFactory.CreateArrayItem(TestSyntaxFactory.CreateString("1")), TestSyntaxFactory.CreateArrayItem(TestSyntaxFactory.CreateString("2")) })) }); var hierarchy = new SyntaxHierarchy(); hierarchy.AddRoot(obj); var(narrowedType, diagnostics) = NarrowTypeAndCollectDiagnostics(hierarchy, obj, CreateDummyResourceType()); diagnostics.Should().BeEmpty(); }
public void InvalidArrayValuesShouldBeRejected() { var obj = TestSyntaxFactory.CreateObject(new[] { TestSyntaxFactory.CreateProperty("name", TestSyntaxFactory.CreateString("test")), // zones is an array of strings - set wrong item types TestSyntaxFactory.CreateProperty("zones", TestSyntaxFactory.CreateArray(new[] { TestSyntaxFactory.CreateArrayItem(TestSyntaxFactory.CreateBool(true)), TestSyntaxFactory.CreateArrayItem(TestSyntaxFactory.CreateInt(2)) })), // this property is an array - specify a string instead TestSyntaxFactory.CreateProperty("managedByExtended", TestSyntaxFactory.CreateString("not an array")) }); var hierarchy = new SyntaxHierarchy(); hierarchy.AddRoot(obj); var(narrowedType, diagnostics) = NarrowTypeAndCollectDiagnostics(hierarchy, obj, CreateDummyResourceType()); diagnostics.OrderBy(x => x.Message).Should().HaveDiagnostics(new[] {
public TypeManager(IResourceTypeProvider resourceTypeProvider, IReadOnlyDictionary <SyntaxBase, Symbol> bindings, IReadOnlyDictionary <DeclaredSymbol, ImmutableArray <DeclaredSymbol> > cyclesBySymbol, SyntaxHierarchy hierarchy, ResourceScopeType targetScope) { this.ResourceTypeProvider = resourceTypeProvider; // bindings will be modified by name binding after this object is created // so we can't make an immutable copy here // (using the IReadOnlyDictionary to prevent accidental mutation) this.typeAssignmentVisitor = new TypeAssignmentVisitor(resourceTypeProvider, this, bindings, cyclesBySymbol, hierarchy, targetScope); this.declaredTypeManager = new DeclaredTypeManager(hierarchy, this, resourceTypeProvider, bindings, cyclesBySymbol, targetScope); }