Exemplo n.º 1
0
 public BicepCompletionContext(
     BicepCompletionContextKind kind,
     Range replacementRange,
     SyntaxBase?enclosingDeclaration,
     ObjectSyntax? @object,
     ObjectPropertySyntax?property,
     ArraySyntax?array,
     PropertyAccessSyntax?propertyAccess,
     ResourceAccessSyntax?resourceAccess,
     ArrayAccessSyntax?arrayAccess,
     TargetScopeSyntax?targetScope,
     ImmutableArray <ILanguageScope> activeScopes)
 {
     this.Kind                 = kind;
     this.ReplacementRange     = replacementRange;
     this.EnclosingDeclaration = enclosingDeclaration;
     this.Object               = @object;
     this.Property             = property;
     this.Array                = array;
     this.PropertyAccess       = propertyAccess;
     this.ResourceAccess       = resourceAccess;
     this.ArrayAccess          = arrayAccess;
     this.TargetScope          = targetScope;
     this.ActiveScopes         = activeScopes;
 }
Exemplo n.º 2
0
        public override void VisitResourceDeclarationSyntax(ResourceDeclarationSyntax syntax)
        {
            // This check is separate from IsLoopAllowedHere because this is about the appearance of a
            // nested resource **inside** a loop.
            if (this.semanticModel.Binder.GetNearestAncestor <ForSyntax>(syntax) is ForSyntax)
            {
                this.diagnosticWriter.Write(DiagnosticBuilder.ForPosition(syntax.Span).NestedResourceNotAllowedInLoop());
            }

            // Resources can be nested, support recursion of resource declarations
            var previousLoopCapableTopLevelDeclaration = this.activeLoopCapableTopLevelDeclaration;

            this.activeLoopCapableTopLevelDeclaration = syntax;

            // stash the body (handles loops and conditions as well)
            var previousDependsOnProperty = this.currentDependsOnProperty;

            this.currentDependsOnProperty = TryGetDependsOnProperty(syntax.TryGetBody());

            base.VisitResourceDeclarationSyntax(syntax);

            // restore state
            this.currentDependsOnProperty             = previousDependsOnProperty;
            this.activeLoopCapableTopLevelDeclaration = previousLoopCapableTopLevelDeclaration;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Returns the specified property by name on any valid or invalid object syntax node if there is exactly one property by that name.
        /// Returns null if the property does not exist or if multiple properties by that name exist. This method is intended for a single
        /// one-off property lookup and avoids allocation of a dictionary. If you need to make multiple look ups, use another extension in this class.
        /// </summary>
        /// <param name="syntax">The object syntax node</param>
        /// <param name="propertyName">The property name</param>
        public static ObjectPropertySyntax?TryGetPropertyByName(this ObjectSyntax syntax, string propertyName)
        {
            ObjectPropertySyntax?result = null;

            var matchingValidProperties = syntax.Properties
                                          .Where(p => p.TryGetKeyText() is { } validName&& string.Equals(validName, propertyName, LanguageConstants.IdentifierComparison));

            foreach (var property in matchingValidProperties)
            {
                if (result == null)
                {
                    // we have not yet seen a name match
                    // store it
                    result = property;
                }
                else
                {
                    // we have already seen a name match, which means we have a duplicate property
                    // no point proceeding any further
                    return(null);
                }
            }

            return(result);
        }
Exemplo n.º 4
0
        public override void VisitModuleDeclarationSyntax(ModuleDeclarationSyntax syntax)
        {
            this.activeLoopCapableTopLevelDeclaration = syntax;

            // stash the body (handles loops and conditions as well)
            this.currentDependsOnProperty = TryGetDependsOnProperty(syntax.TryGetBody());

            base.VisitModuleDeclarationSyntax(syntax);

            // clear the stash
            this.currentDependsOnProperty = null;

            this.activeLoopCapableTopLevelDeclaration = null;
        }
Exemplo n.º 5
0
 public BicepCompletionContext(
     BicepCompletionContextKind kind,
     Range replacementRange,
     SyntaxBase?enclosingDeclaration,
     ObjectSyntax? @object,
     ObjectPropertySyntax?property,
     ArraySyntax?array,
     PropertyAccessSyntax?propertyAccess,
     TargetScopeSyntax?targetScope)
 {
     this.Kind                 = kind;
     this.ReplacementRange     = replacementRange;
     this.EnclosingDeclaration = enclosingDeclaration;
     this.Object               = @object;
     this.Property             = property;
     this.Array                = array;
     this.PropertyAccess       = propertyAccess;
     this.TargetScope          = targetScope;
 }
Exemplo n.º 6
0
        private static ScopeData?ValidateScope(SemanticModel semanticModel, LogInvalidScopeDiagnostic logInvalidScopeFunc, ResourceScope supportedScopes, SyntaxBase bodySyntax, ObjectPropertySyntax?scopeProperty)
        {
            if (scopeProperty is null)
            {
                // no scope provided - use the target scope for the file
                if (!supportedScopes.HasFlag(semanticModel.TargetScope))
                {
                    logInvalidScopeFunc(bodySyntax, semanticModel.TargetScope, supportedScopes);
                    return(null);
                }

                return(null);
            }

            var scopeSymbol = semanticModel.GetSymbolInfo(scopeProperty.Value);
            var scopeType   = semanticModel.GetTypeInfo(scopeProperty.Value);

            switch (scopeType)
            {
            case TenantScopeType type:
                if (!supportedScopes.HasFlag(ResourceScope.Tenant))
                {
                    logInvalidScopeFunc(scopeProperty.Value, ResourceScope.Tenant, supportedScopes);
                    return(null);
                }

                return(new ScopeData {
                    RequestedScope = ResourceScope.Tenant
                });

            case ManagementGroupScopeType type:
                if (!supportedScopes.HasFlag(ResourceScope.ManagementGroup))
                {
                    logInvalidScopeFunc(scopeProperty.Value, ResourceScope.ManagementGroup, supportedScopes);
                    return(null);
                }

                return(type.Arguments.Length switch {
                    0 => new ScopeData {
                        RequestedScope = ResourceScope.ManagementGroup
                    },
                    _ => new ScopeData {
                        RequestedScope = ResourceScope.ManagementGroup, ManagementGroupNameProperty = type.Arguments[0].Expression
                    },
                });
Exemplo n.º 7
0
        private static ScopeData?ValidateScope(SemanticModel semanticModel, LogInvalidScopeDiagnostic logInvalidScopeFunc, ResourceScope supportedScopes, SyntaxBase bodySyntax, ObjectPropertySyntax?scopeProperty)
        {
            if (scopeProperty is null)
            {
                // no scope provided - use the target scope for the file
                if (!supportedScopes.HasFlag(semanticModel.TargetScope))
                {
                    logInvalidScopeFunc(bodySyntax, semanticModel.TargetScope, supportedScopes);
                    return(null);
                }

                return(null);
            }

            var(scopeSymbol, indexExpression) = scopeProperty.Value switch
            {
                // scope indexing can only happen with references to module or resource collections
                ArrayAccessSyntax {
                    BaseExpression : VariableAccessSyntax baseVariableAccess
                } arrayAccess => (semanticModel.GetSymbolInfo(baseVariableAccess), arrayAccess.IndexExpression),

                // all other scope expressions
                _ => (semanticModel.GetSymbolInfo(scopeProperty.Value), null)
            };

            var scopeType = semanticModel.GetTypeInfo(scopeProperty.Value);

            switch (scopeType)
            {
            case TenantScopeType type:
                if (!supportedScopes.HasFlag(ResourceScope.Tenant))
                {
                    logInvalidScopeFunc(scopeProperty.Value, ResourceScope.Tenant, supportedScopes);
                    return(null);
                }

                return(new ScopeData {
                    RequestedScope = ResourceScope.Tenant, IndexExpression = indexExpression
                });

            case ManagementGroupScopeType type:
                if (!supportedScopes.HasFlag(ResourceScope.ManagementGroup))
                {
                    logInvalidScopeFunc(scopeProperty.Value, ResourceScope.ManagementGroup, supportedScopes);
                    return(null);
                }

                return(type.Arguments.Length switch
                {
                    0 => new ScopeData {
                        RequestedScope = ResourceScope.ManagementGroup, IndexExpression = indexExpression
                    },
                    _ => new ScopeData {
                        RequestedScope = ResourceScope.ManagementGroup, ManagementGroupNameProperty = type.Arguments[0].Expression, IndexExpression = indexExpression
                    },
                });
Exemplo n.º 8
0
        private static ScopeData?ValidateScope(SemanticModel semanticModel, LogInvalidScopeDiagnostic logInvalidScopeFunc, ResourceScope supportedScopes, SyntaxBase bodySyntax, ObjectPropertySyntax?scopeProperty)
        {
            if (scopeProperty is null)
            {
                // no scope provided - use the target scope for the file
                if (!supportedScopes.HasFlag(semanticModel.TargetScope))
                {
                    logInvalidScopeFunc(bodySyntax, semanticModel.TargetScope, supportedScopes);
                    return(null);
                }

                return(null);
            }

            var scopeSymbol = scopeProperty.Value switch
            {
                // scope indexing can only happen with references to module or resource collections
                ArrayAccessSyntax {
                    BaseExpression : VariableAccessSyntax baseVariableAccess
                } => semanticModel.GetSymbolInfo(baseVariableAccess),
Exemplo n.º 9
0
 public BicepCompletionContext(BicepCompletionContextKind kind, SyntaxBase?enclosingDeclaration = null, ObjectSyntax? @object = null, ObjectPropertySyntax?property = null, ArraySyntax?array = null)
 {
     this.Kind = kind;
     this.EnclosingDeclaration = enclosingDeclaration;
     this.Object   = @object;
     this.Property = property;
     this.Array    = array;
 }