Beispiel #1
0
        public override void VisitResourceAccessSyntax(ResourceAccessSyntax syntax)
        {
            this.ValidateDirectAccessToResourceOrModuleCollection(syntax);

            // visit children
            base.VisitResourceAccessSyntax(syntax);
        }
Beispiel #2
0
        public async Task HoveringOverSymbolReferencesAndDeclarationsShouldProduceHovers(DataSet dataSet)
        {
            var compilation = dataSet.CopyFilesAndCreateCompilation(TestContext, out _, out var fileUri);
            var uri         = DocumentUri.From(fileUri);
            var client      = await IntegrationTestHelper.StartServerWithTextAsync(this.TestContext, dataSet.Bicep, uri, resourceTypeProvider : AzResourceTypeProvider.CreateWithAzTypes(), fileResolver : BicepTestConstants.FileResolver);

            var symbolTable = compilation.ReconstructSymbolTable();
            var lineStarts  = compilation.SyntaxTreeGrouping.EntryPoint.LineStarts;

            var symbolReferences = SyntaxAggregator.Aggregate(
                compilation.SyntaxTreeGrouping.EntryPoint.ProgramSyntax,
                new List <SyntaxBase>(),
                (accumulated, node) =>
            {
                if (node is ISymbolReference || node is ITopLevelNamedDeclarationSyntax)
                {
                    accumulated.Add(node);
                }

                return(accumulated);
            },
                accumulated => accumulated);

            foreach (var symbolReference in symbolReferences)
            {
                // by default, request a hover on the first character of the syntax, but for certain syntaxes, this doesn't make sense.
                // for example on an instance function call 'az.resourceGroup()', it only makes sense to request a hover on the 3rd character.
                var nodeForHover = symbolReference switch
                {
                    ITopLevelDeclarationSyntax d => d.Keyword,
                    ResourceAccessSyntax r => r.ResourceName,
                    FunctionCallSyntaxBase f => f.Name,
                         _ => symbolReference,
                };

                var hover = await client.RequestHover(new HoverParams
                {
                    TextDocument = new TextDocumentIdentifier(uri),
                    Position     = TextCoordinateConverter.GetPosition(lineStarts, nodeForHover.Span.Position)
                });

                // fancy method to give us some annotated source code to look at if any assertions fail :)
                using (new AssertionScope().WithVisualCursor(compilation.SyntaxTreeGrouping.EntryPoint, nodeForHover.Span.ToZeroLengthSpan()))
                {
                    if (!symbolTable.TryGetValue(symbolReference, out var symbol))
                    {
                        if (symbolReference is InstanceFunctionCallSyntax &&
                            compilation.GetEntrypointSemanticModel().GetSymbolInfo(symbolReference) is FunctionSymbol ifcSymbol)
                        {
                            ValidateHover(hover, ifcSymbol);
                            break;
                        }

                        // symbol ref not bound to a symbol
                        hover.Should().BeNull();
                        continue;
                    }

                    switch (symbol !.Kind)
                    {
Beispiel #3
0
        private DeclaredTypeAssignment?GetResourceAccessType(ResourceAccessSyntax syntax)
        {
            if (!syntax.ResourceName.IsValid)
            {
                return(null);
            }

            // We should already have a symbol, use its type.
            var symbol = this.binder.GetSymbolInfo(syntax);

            if (symbol == null)
            {
                throw new InvalidOperationException("ResourceAccessSyntax was not assigned a symbol during name binding.");
            }

            if (symbol is ErrorSymbol error)
            {
                return(new DeclaredTypeAssignment(ErrorType.Create(error.GetDiagnostics()), syntax));
            }
            else if (symbol is not ResourceSymbol resourceSymbol)
            {
                var baseType   = GetDeclaredType(syntax.BaseExpression);
                var typeString = baseType?.Kind.ToString() ?? LanguageConstants.ErrorName;
                return(new DeclaredTypeAssignment(ErrorType.Create(DiagnosticBuilder.ForPosition(syntax.ResourceName).ResourceRequiredForResourceAccess(typeString)), syntax));
            }
        public override void VisitResourceAccessSyntax(ResourceAccessSyntax syntax)
        {
            if (!currentDeclarations.TryPeek(out var currentDeclaration))
            {
                // we're not inside a declaration, so there should be no risk of a cycle
                return;
            }

            declarationAccessDict[currentDeclaration].Add(syntax);
            base.VisitResourceAccessSyntax(syntax);
        }
Beispiel #5
0
        public override void VisitResourceAccessSyntax(ResourceAccessSyntax syntax)
        {
            base.VisitResourceAccessSyntax(syntax);

            // we need to resolve which resource delaration the LHS is pointing to - and then
            // validate that we can resolve the name.
            this.bindings.TryGetValue(syntax.BaseExpression, out var symbol);

            if (symbol is ErrorSymbol)
            {
                this.bindings.Add(syntax, symbol);
                return;
            }
            else if (symbol is null || symbol is not ResourceSymbol)
            {
                // symbol could be null in the case of an incomplete expression during parsing like `a:`
                var error = new ErrorSymbol(DiagnosticBuilder.ForPosition(syntax.ResourceName).ResourceRequiredForResourceAccess(symbol?.Kind.ToString() ?? LanguageConstants.ErrorName));
                this.bindings.Add(syntax, error);
                return;
            }

            // This is the symbol of LHS and it's a valid resource.
            var resourceSymbol = (ResourceSymbol)symbol;
            var resourceBody   = resourceSymbol.DeclaringResource.TryGetBody();

            if (resourceBody == null)
            {
                // If we have no body then there will be nothing to reference.
                var error = new ErrorSymbol(DiagnosticBuilder.ForPosition(syntax.ResourceName).NestedResourceNotFound(resourceSymbol.Name, syntax.ResourceName.IdentifierName, nestedResourceNames: new [] { "(none)", }));
                this.bindings.Add(syntax, error);
                return;
            }

            if (!this.allLocalScopes.TryGetValue(resourceBody, out var localScope))
            {
                // code defect in the declaration visitor
                throw new InvalidOperationException($"Local scope is missing for {syntax.GetType().Name} at {syntax.Span}");
            }

            var referencedResource = LookupResourceSymbolByName(localScope, syntax.ResourceName);

            if (referencedResource is null)
            {
                var nestedResourceNames = localScope.Declarations.OfType <ResourceSymbol>().Select(r => r.Name);
                var error = new ErrorSymbol(DiagnosticBuilder.ForPosition(syntax.ResourceName).NestedResourceNotFound(resourceSymbol.Name, syntax.ResourceName.IdentifierName, nestedResourceNames));
                this.bindings.Add(syntax, error);
                return;
            }

            // This is valid.
            this.bindings.Add(syntax, referencedResource);
        }
Beispiel #6
0
        public async Task HoveringOverSymbolReferencesAndDeclarationsShouldProduceHovers(DataSet dataSet)
        {
            var uri    = DocumentUri.From($"/{dataSet.Name}");
            var client = await IntegrationTestHelper.StartServerWithTextAsync(dataSet.Bicep, uri, resourceTypeProvider : new AzResourceTypeProvider(new TypeLoader()));

            // construct a parallel compilation
            var compilation = dataSet.CopyFilesAndCreateCompilation(TestContext, out _);

            var symbolTable = compilation.ReconstructSymbolTable();
            var lineStarts  = compilation.SyntaxTreeGrouping.EntryPoint.LineStarts;

            var symbolReferences = SyntaxAggregator.Aggregate(
                compilation.SyntaxTreeGrouping.EntryPoint.ProgramSyntax,
                new List <SyntaxBase>(),
                (accumulated, node) =>
            {
                if (node is ISymbolReference || node is ITopLevelNamedDeclarationSyntax)
                {
                    accumulated.Add(node);
                }

                return(accumulated);
            },
                accumulated => accumulated);

            foreach (SyntaxBase symbolReference in symbolReferences)
            {
                var nodeForHover = symbolReference switch
                {
                    ITopLevelDeclarationSyntax d => d.Keyword,
                    ResourceAccessSyntax r => r.ResourceName,
                                _ => symbolReference,
                };

                var hover = await client.RequestHover(new HoverParams
                {
                    TextDocument = new TextDocumentIdentifier(uri),
                    Position     = PositionHelper.GetPosition(lineStarts, nodeForHover.Span.Position)
                });

                // fancy method to give us some annotated source code to look at if any assertions fail :)
                using (CreateAssertionScopeWithContext(compilation.SyntaxTreeGrouping.EntryPoint, hover, nodeForHover.Span.ToZeroLengthSpan()))
                {
                    if (symbolTable.TryGetValue(symbolReference, out var symbol) == false)
                    {
                        // symbol ref not bound to a symbol
                        hover.Should().BeNull();
                        continue;
                    }

                    switch (symbol !.Kind)
                    {
Beispiel #7
0
 public override void VisitResourceAccessSyntax(ResourceAccessSyntax syntax) =>
 this.BuildWithConcat(() => base.VisitResourceAccessSyntax(syntax));
Beispiel #8
0
 public override void VisitResourceAccessSyntax(ResourceAccessSyntax syntax)
 {
     this.buffer.Append('(');
     base.VisitResourceAccessSyntax(syntax);
     this.buffer.Append(')');
 }