forked from Azure/bicep
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCompilation.cs
83 lines (71 loc) · 4.46 KB
/
Compilation.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections.Immutable;
using System.Linq;
using Bicep.Core.Analyzers.Interfaces;
using Bicep.Core.Configuration;
using Bicep.Core.Diagnostics;
using Bicep.Core.Features;
using Bicep.Core.Extensions;
using Bicep.Core.Semantics.Namespaces;
using Bicep.Core.Workspaces;
using Bicep.Core.Analyzers.Linter.ApiVersions;
namespace Bicep.Core.Semantics
{
public class Compilation
{
// Stores semantic model for each source file (map exists for all source files, but semantic model created only when indexed)
private readonly ImmutableDictionary<ISourceFile, Lazy<ISemanticModel>> lazySemanticModelLookup;
private readonly IConfigurationManager configurationManager;
private readonly IFeatureProviderFactory featureProviderFactory;
private readonly IApiVersionProviderFactory apiVersionProviderFactory;
private readonly IBicepAnalyzer linterAnalyzer;
public Compilation(IFeatureProviderFactory featureProviderFactory, INamespaceProvider namespaceProvider, SourceFileGrouping sourceFileGrouping, IConfigurationManager configurationManager, IApiVersionProviderFactory apiVersionProviderFactory, IBicepAnalyzer linterAnalyzer, ImmutableDictionary<ISourceFile, ISemanticModel>? modelLookup = null)
{
this.featureProviderFactory = featureProviderFactory;
this.SourceFileGrouping = sourceFileGrouping;
this.NamespaceProvider = namespaceProvider;
this.configurationManager = configurationManager;
this.apiVersionProviderFactory = apiVersionProviderFactory;
this.linterAnalyzer = linterAnalyzer;
this.lazySemanticModelLookup = sourceFileGrouping.SourceFiles.ToImmutableDictionary(
sourceFile => sourceFile,
sourceFile => (modelLookup is not null && modelLookup.TryGetValue(sourceFile, out var existingModel)) ?
new(existingModel) :
new Lazy<ISemanticModel>(() => sourceFile switch // semantic model doesn't yet exist for file, create it
{
BicepFile bicepFile => CreateSemanticModel(bicepFile),
BicepParamFile bicepParamFile => CreateSemanticModel(bicepParamFile),
ArmTemplateFile armTemplateFile => new ArmTemplateSemanticModel(armTemplateFile),
TemplateSpecFile templateSpecFile => new TemplateSpecSemanticModel(templateSpecFile),
_ => throw new ArgumentOutOfRangeException(nameof(sourceFile)),
}));
}
public SourceFileGrouping SourceFileGrouping { get; }
public INamespaceProvider NamespaceProvider { get; }
public SemanticModel GetEntrypointSemanticModel()
// entry point semantic models are guaranteed to cast successfully
=> GetSemanticModel(SourceFileGrouping.EntryPoint);
public SemanticModel GetSemanticModel(BicepSourceFile bicepFile)
=> this.GetSemanticModel<SemanticModel>(bicepFile);
public ArmTemplateSemanticModel GetSemanticModel(ArmTemplateFile armTemplateFile)
=> this.GetSemanticModel<ArmTemplateSemanticModel>(armTemplateFile);
public ISemanticModel GetSemanticModel(ISourceFile sourceFile)
=> this.lazySemanticModelLookup[sourceFile].Value;
public ImmutableDictionary<BicepSourceFile, ImmutableArray<IDiagnostic>> GetAllDiagnosticsByBicepFile()
=> SourceFileGrouping.SourceFiles.OfType<BicepSourceFile>().ToImmutableDictionary(
bicepFile => bicepFile,
bicepFile => this.GetSemanticModel(bicepFile) is SemanticModel semanticModel ? semanticModel.GetAllDiagnostics() : ImmutableArray<IDiagnostic>.Empty);
private T GetSemanticModel<T>(ISourceFile sourceFile) where T : class, ISemanticModel =>
this.GetSemanticModel(sourceFile) as T ??
throw new ArgumentException($"Expected the semantic model type to be \"{typeof(T).Name}\".");
private SemanticModel CreateSemanticModel(BicepSourceFile bicepFile) => new SemanticModel(this,
bicepFile,
SourceFileGrouping.FileResolver,
linterAnalyzer,
configurationManager.GetConfiguration(bicepFile.FileUri),
featureProviderFactory.GetFeatureProvider(bicepFile.FileUri),
apiVersionProviderFactory.GetApiVersionProvider(bicepFile.FileUri));
}
}