Пример #1
0
        public static string?TryGetDescription(SemanticModel semanticModel, StatementSyntax statement)
        {
            var decorator = SemanticModelHelper.TryGetDecoratorInNamespace(semanticModel,
                                                                           statement,
                                                                           SystemNamespaceType.BuiltInName,
                                                                           LanguageConstants.MetadataDescriptionPropertyName);

            if (decorator is not null &&
                decorator.Arguments.FirstOrDefault()?.Expression is StringSyntax stringSyntax &&
                stringSyntax.TryGetLiteralValue() is string description)
            {
                return(description);
            }

            return(null);
        }
Пример #2
0
        public SemanticModel(Compilation compilation, BicepFile sourceFile, IFileResolver fileResolver, RootConfiguration configuration)
        {
            Trace.WriteLine($"Building semantic model for {sourceFile.FileUri}");

            Compilation   = compilation;
            SourceFile    = sourceFile;
            FileResolver  = fileResolver;
            Configuration = configuration;

            // 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(compilation, this);

            SymbolContext = symbolContext;

            Binder      = new Binder(compilation.NamespaceProvider, sourceFile, symbolContext);
            TypeManager = new TypeManager(Binder, fileResolver);

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

            this.emitLimitationInfoLazy = new Lazy <EmitLimitationInfo>(() => EmitLimitationCalculator.Calculate(this));
            this.symbolHierarchyLazy    = new Lazy <SymbolHierarchy>(() =>
            {
                var hierarchy = new SymbolHierarchy();
                hierarchy.AddRoot(this.Root);

                return(hierarchy);
            });
            this.resourceAncestorsLazy = new Lazy <ResourceAncestorGraph>(() => ResourceAncestorGraph.Compute(this));
            this.ResourceMetadata      = new ResourceMetadataCache(this);

            // lazy loading the linter will delay linter rule loading
            // and configuration loading until the linter is actually needed
            this.linterAnalyzerLazy = new Lazy <LinterAnalyzer>(() => new LinterAnalyzer(configuration));

            this.allResourcesLazy = new Lazy <ImmutableArray <ResourceMetadata> >(() => GetAllResourceMetadata());

            // lazy load single use diagnostic set
            this.allDiagnostics = new Lazy <IEnumerable <IDiagnostic> >(() => AssembleDiagnostics());

            this.parameterTypePropertiesLazy = new Lazy <ImmutableArray <TypeProperty> >(() =>
            {
                var paramTypeProperties = new List <TypeProperty>();

                foreach (var param in this.Root.ParameterDeclarations.DistinctBy(p => p.Name))
                {
                    var typePropertyFlags = TypePropertyFlags.WriteOnly;
                    if (SyntaxHelper.TryGetDefaultValue(param.DeclaringParameter) == null)
                    {
                        // if there's no default value, it must be specified
                        typePropertyFlags |= TypePropertyFlags.Required;
                    }

                    var description = SemanticModelHelper.TryGetDescription(this, param.DeclaringParameter);
                    paramTypeProperties.Add(new TypeProperty(param.Name, param.Type, typePropertyFlags, description));
                }

                return(paramTypeProperties.ToImmutableArray());
            });

            this.outputTypePropertiesLazy = new Lazy <ImmutableArray <TypeProperty> >(() =>
            {
                var outputTypeProperties = new List <TypeProperty>();

                foreach (var output in this.Root.OutputDeclarations.DistinctBy(o => o.Name))
                {
                    var description = SemanticModelHelper.TryGetDescription(this, output.DeclaringOutput);
                    outputTypeProperties.Add(new TypeProperty(output.Name, output.Type, TypePropertyFlags.ReadOnly, description));
                }

                return(outputTypeProperties.ToImmutableArray());
            });
        }
Пример #3
0
        public SemanticModel(Compilation compilation, BicepFile sourceFile, IFileResolver fileResolver, IBicepAnalyzer linterAnalyzer)
        {
            Trace.WriteLine($"Building semantic model for {sourceFile.FileUri}");

            Compilation  = compilation;
            SourceFile   = sourceFile;
            FileResolver = fileResolver;

            // 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(compilation, this);

            SymbolContext = symbolContext;

            Binder      = new Binder(compilation.NamespaceProvider, sourceFile, symbolContext);
            TypeManager = new TypeManager(compilation.Features, Binder, fileResolver);

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

            this.emitLimitationInfoLazy = new Lazy <EmitLimitationInfo>(() => EmitLimitationCalculator.Calculate(this));
            this.symbolHierarchyLazy    = new Lazy <SymbolHierarchy>(() =>
            {
                var hierarchy = new SymbolHierarchy();
                hierarchy.AddRoot(this.Root);

                return(hierarchy);
            });
            this.resourceAncestorsLazy = new Lazy <ResourceAncestorGraph>(() => ResourceAncestorGraph.Compute(this));
            this.ResourceMetadata      = new ResourceMetadataCache(this);

            LinterAnalyzer = linterAnalyzer;

            this.allResourcesLazy      = new Lazy <ImmutableArray <ResourceMetadata> >(() => GetAllResourceMetadata());
            this.declaredResourcesLazy = new Lazy <ImmutableArray <DeclaredResourceMetadata> >(() => this.AllResources.OfType <DeclaredResourceMetadata>().ToImmutableArray());

            // lazy load single use diagnostic set
            this.allDiagnostics = new Lazy <IEnumerable <IDiagnostic> >(() => AssembleDiagnostics());

            this.parametersLazy = new Lazy <ImmutableArray <ParameterMetadata> >(() =>
            {
                var parameters = new List <ParameterMetadata>();

                foreach (var param in this.Root.ParameterDeclarations.DistinctBy(p => p.Name))
                {
                    var description = SemanticModelHelper.TryGetDescription(this, param.DeclaringParameter);
                    var isRequired  = SyntaxHelper.TryGetDefaultValue(param.DeclaringParameter) == null;
                    if (param.Type is ResourceType resourceType)
                    {
                        // Resource type parameters are a special case, we need to convert to a dedicated
                        // type so we can compare differently for assignment.
                        var type = new UnboundResourceType(resourceType.TypeReference);
                        parameters.Add(new ParameterMetadata(param.Name, type, isRequired, description));
                    }
                    else
                    {
                        parameters.Add(new ParameterMetadata(param.Name, param.Type, isRequired, description));
                    }
                }

                return(parameters.ToImmutableArray());
            });

            this.outputsLazy = new Lazy <ImmutableArray <OutputMetadata> >(() =>
            {
                var outputs = new List <OutputMetadata>();

                foreach (var output in this.Root.OutputDeclarations.DistinctBy(o => o.Name))
                {
                    var description = SemanticModelHelper.TryGetDescription(this, output.DeclaringOutput);
                    if (output.Type is ResourceType resourceType)
                    {
                        // Resource type parameters are a special case, we need to convert to a dedicated
                        // type so we can compare differently for assignment and code generation.
                        var type = new UnboundResourceType(resourceType.TypeReference);
                        outputs.Add(new OutputMetadata(output.Name, type, description));
                    }
                    else
                    {
                        outputs.Add(new OutputMetadata(output.Name, output.Type, description));
                    }
                }

                return(outputs.ToImmutableArray());
            });
        }