public async Task <Compilation> CompileAsync(string inputPath, bool skipRestore) { var inputUri = PathHelper.FilePathToFileUrl(inputPath); var configuration = this.configurationManager.GetConfiguration(inputUri); var sourceFileGrouping = SourceFileGroupingBuilder.Build(this.fileResolver, this.moduleDispatcher, this.workspace, inputUri, configuration); if (!skipRestore) { // module references in the file may be malformed // however we still want to surface as many errors as we can for the module refs that are valid // so we will try to restore modules with valid refs and skip everything else // (the diagnostics will be collected during compilation) if (await moduleDispatcher.RestoreModules(configuration, moduleDispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration))) { // modules had to be restored - recompile sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(moduleDispatcher, this.workspace, sourceFileGrouping, configuration); } } var compilation = new Compilation(this.invocationContext.NamespaceProvider, sourceFileGrouping, configuration, new LinterAnalyzer(configuration)); LogDiagnostics(compilation); return(compilation); }
public void ValidBicepTextWriter_TemplateEmiterShouldProduceExpectedTemplate(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); MemoryStream memoryStream = new MemoryStream(); // emitting the template should be successful FileResolver fileResolver = BicepTestConstants.FileResolver; var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver)); var result = this.EmitTemplate(SourceFileGroupingBuilder.Build(fileResolver, dispatcher, new Workspace(), PathHelper.FilePathToFileUrl(bicepFilePath)), memoryStream, BicepTestConstants.DevAssemblyFileVersion); result.Diagnostics.Should().NotHaveErrors(); result.Status.Should().Be(EmitStatus.Succeeded); // normalizing the formatting in case there are differences in indentation // this way the diff between actual and expected will be clean var actual = JToken.ReadFrom(new JsonTextReader(new StreamReader(new MemoryStream(memoryStream.ToArray())))); var compiledFilePath = FileHelper.SaveResultFile(this.TestContext, Path.Combine(dataSet.Name, DataSet.TestFileMainCompiled), actual.ToString(Formatting.Indented)); actual.Should().EqualWithJsonDiffOutput( TestContext, JToken.Parse(dataSet.Compiled !), expectedLocation: DataSet.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainCompiled), actualLocation: compiledFilePath); }
private bool RewriteSyntax(Workspace workspace, Uri entryUri, Func <SemanticModel, SyntaxRewriteVisitor> rewriteVisitorBuilder) { var hasChanges = false; var dispatcher = new ModuleDispatcher(this.registryProvider); var configuration = configurationManager.GetBuiltInConfiguration(disableAnalyzers: true); var linterAnalyzer = new LinterAnalyzer(configuration); var sourceFileGrouping = SourceFileGroupingBuilder.Build(fileResolver, dispatcher, workspace, entryUri, configuration); var compilation = new Compilation(this.features, namespaceProvider, sourceFileGrouping, configuration, linterAnalyzer); // force enumeration here with .ToImmutableArray() as we're going to be modifying the sourceFileGrouping collection as we iterate var fileUris = sourceFileGrouping.SourceFiles.Select(x => x.FileUri).ToImmutableArray(); foreach (var fileUri in fileUris) { if (sourceFileGrouping.SourceFiles.FirstOrDefault(x => x.FileUri == fileUri) is not BicepFile bicepFile) { throw new InvalidOperationException($"Failed to find a bicep source file for URI {fileUri}."); } var newProgramSyntax = rewriteVisitorBuilder(compilation.GetSemanticModel(bicepFile)).Rewrite(bicepFile.ProgramSyntax); if (!object.ReferenceEquals(bicepFile.ProgramSyntax, newProgramSyntax)) { hasChanges = true; var newFile = SourceFileFactory.CreateBicepFile(fileUri, newProgramSyntax.ToText()); workspace.UpsertSourceFile(newFile); sourceFileGrouping = SourceFileGroupingBuilder.Build(fileResolver, dispatcher, workspace, entryUri, configuration); compilation = new Compilation(this.features, namespaceProvider, sourceFileGrouping, configuration, linterAnalyzer); } } return(hasChanges); }
private static bool RewriteSyntax(IResourceTypeProvider resourceTypeProvider, Workspace workspace, Uri entryUri, Func <SemanticModel, SyntaxRewriteVisitor> rewriteVisitorBuilder) { var hasChanges = false; var fileResolver = new FileResolver(); var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(fileResolver)); var sourceFileGrouping = SourceFileGroupingBuilder.Build(fileResolver, dispatcher, workspace, entryUri); var compilation = new Compilation(resourceTypeProvider, sourceFileGrouping); foreach (var(fileUri, sourceFile) in workspace.GetActiveSourceFilesByUri()) { if (sourceFile is not BicepFile bicepFile) { throw new InvalidOperationException("Expected a bicep source file."); } var newProgramSyntax = rewriteVisitorBuilder(compilation.GetSemanticModel(bicepFile)).Rewrite(bicepFile.ProgramSyntax); if (!object.ReferenceEquals(bicepFile.ProgramSyntax, newProgramSyntax)) { hasChanges = true; var newFile = new BicepFile(fileUri, ImmutableArray <int> .Empty, newProgramSyntax); workspace.UpsertSourceFile(newFile); sourceFileGrouping = SourceFileGroupingBuilder.Build(fileResolver, dispatcher, workspace, entryUri); compilation = new Compilation(resourceTypeProvider, sourceFileGrouping); } } return(hasChanges); }
public static SourceFileGrouping CreateForFiles(IReadOnlyDictionary <Uri, string> fileContentsByUri, Uri entryFileUri, IFileResolver fileResolver) { var workspace = new Workspace(); var sourceFiles = fileContentsByUri.Select(kvp => SourceFileFactory.CreateSourceFile(kvp.Key, kvp.Value)); workspace.UpsertSourceFiles(sourceFiles); return(SourceFileGroupingBuilder.Build(fileResolver, new ModuleDispatcher(new DefaultModuleRegistryProvider(fileResolver)), workspace, entryFileUri)); }
public static Compilation CopyFilesAndCreateCompilation(this DataSet dataSet, TestContext testContext, out string outputDirectory, out Uri fileUri) { outputDirectory = dataSet.SaveFilesToTestDirectory(testContext); fileUri = PathHelper.FilePathToFileUrl(Path.Combine(outputDirectory, DataSet.TestFileMain)); var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver)); var sourceFileGrouping = SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, new Workspace(), fileUri); return(new Compilation(AzResourceTypeProvider.CreateWithAzTypes(), sourceFileGrouping)); }
public async Task RestoreAsync(string inputPath) { var inputUri = PathHelper.FilePathToFileUrl(inputPath); var configuration = this.configurationManager.GetConfiguration(inputUri); var sourceFileGrouping = SourceFileGroupingBuilder.Build(this.fileResolver, this.moduleDispatcher, this.workspace, inputUri, configuration); // restore is supposed to only restore the module references that are valid // and not log any other errors await moduleDispatcher.RestoreModules(configuration, moduleDispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration)); }
private string GenerateCompiledParametersFileAndReturnOutputMessage(string bicepFilePath, DocumentUri documentUri) { string compiledFilePath = PathHelper.ResolveParametersFileOutputPath(bicepFilePath); string compiledFile = Path.GetFileName(compiledFilePath); // If the template exists and contains bicep generator metadata, we can go ahead and replace the file. // If not, we'll fail the generate params. if (File.Exists(compiledFilePath) && !TemplateIsParametersFile(File.ReadAllText(compiledFilePath))) { return("Generating parameters file failed. The file \"" + compiledFile + "\" already exists but does not contain the schema for a parameters file. If overwriting the file is intended, delete it manually and retry the Generate Parameters command."); } var fileUri = documentUri.ToUri(); RootConfiguration?configuration = null; try { configuration = this.configurationManager.GetConfiguration(fileUri); } catch (ConfigurationException exception) { // Fail the generate params if there's configuration errors. return(exception.Message); } CompilationContext?context = compilationManager.GetCompilation(fileUri); Compilation compilation; if (context is null) { SourceFileGrouping sourceFileGrouping = SourceFileGroupingBuilder.Build(this.fileResolver, this.moduleDispatcher, new Workspace(), fileUri, configuration); compilation = new Compilation(features, namespaceProvider, sourceFileGrouping, configuration, new LinterAnalyzer(configuration)); } else { compilation = context.Compilation; } KeyValuePair <BicepFile, IEnumerable <IDiagnostic> > diagnosticsByFile = compilation.GetAllDiagnosticsByBicepFile() .FirstOrDefault(x => x.Key.FileUri == fileUri); if (diagnosticsByFile.Value.Any(x => x.Level == DiagnosticLevel.Error)) { return("Generating parameters file failed. Please fix below errors:\n" + DiagnosticsHelper.GetDiagnosticsMessage(diagnosticsByFile)); } var existingContent = File.Exists(compiledFilePath) ? File.ReadAllText(compiledFilePath) : string.Empty; var emitter = new TemplateEmitter(compilation.GetEntrypointSemanticModel(), emitterSettings); using var fileStream = new FileStream(compiledFilePath, FileMode.Create, FileAccess.Write); var result = emitter.EmitParametersFile(fileStream, existingContent); return("Generating parameters file succeeded. Processed file " + compiledFile); }
private string GenerateCompiledFileAndReturnBuildOutputMessage(string bicepFilePath, DocumentUri documentUri) { string compiledFilePath = PathHelper.GetDefaultBuildOutputPath(bicepFilePath); string compiledFile = Path.GetFileName(compiledFilePath); // If the template exists and contains bicep generator metadata, we can go ahead and replace the file. // If not, we'll fail the build. if (File.Exists(compiledFilePath) && !TemplateContainsBicepGeneratorMetadata(File.ReadAllText(compiledFilePath))) { return("Build failed. The file \"" + compiledFile + "\" already exists and was not generated by Bicep. If overwriting the file is intended, delete it manually and retry the Build command."); } var fileUri = documentUri.ToUri(); RootConfiguration?configuration = null; try { configuration = this.configurationManager.GetConfiguration(fileUri); } catch (ConfigurationException exception) { // Fail the build if there's configuration errors. return(exception.Message); } CompilationContext?context = compilationManager.GetCompilation(fileUri); Compilation compilation; if (context is null) { SourceFileGrouping sourceFileGrouping = SourceFileGroupingBuilder.Build(this.fileResolver, this.moduleDispatcher, new Workspace(), fileUri, configuration); compilation = new Compilation(namespaceProvider, sourceFileGrouping, configuration); } else { compilation = context.Compilation; } KeyValuePair <BicepFile, IEnumerable <IDiagnostic> > diagnosticsByFile = compilation.GetAllDiagnosticsByBicepFile() .FirstOrDefault(x => x.Key.FileUri == fileUri); if (diagnosticsByFile.Value.Any(x => x.Level == DiagnosticLevel.Error)) { return(GetDiagnosticsMessage(diagnosticsByFile)); } using var fileStream = new FileStream(compiledFilePath, FileMode.Create, FileAccess.ReadWrite); var emitter = new TemplateEmitter(compilation.GetEntrypointSemanticModel(), emitterSettings); EmitResult result = emitter.Emit(fileStream); return("Build succeeded. Created file " + compiledFile); }
public void InvalidBicep_TemplateEmiterShouldNotProduceAnyTemplate(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); string filePath = FileHelper.GetResultFilePath(this.TestContext, $"{dataSet.Name}_Compiled_Original.json"); // emitting the template should fail var dispatcher = new ModuleDispatcher(BicepTestConstants.RegistryProvider); var configuration = BicepTestConstants.BuiltInConfigurationWithAnalyzersDisabled; var result = this.EmitTemplate(SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, new Workspace(), PathHelper.FilePathToFileUrl(bicepFilePath), configuration), BicepTestConstants.EmitterSettings, filePath); result.Diagnostics.Should().NotBeEmpty(); result.Status.Should().Be(EmitStatus.Failed); }
private static Compilation GetCompilation(string fileContents) { var fileUri = new Uri("inmemory:///main.bicep"); var workspace = new Workspace(); var sourceFile = SourceFileFactory.CreateSourceFile(fileUri, fileContents); workspace.UpsertSourceFile(sourceFile); var fileResolver = new FileResolver(); var dispatcher = new ModuleDispatcher(new EmptyModuleRegistryProvider()); var sourceFileGrouping = SourceFileGroupingBuilder.Build(fileResolver, dispatcher, workspace, fileUri); return(new Compilation(resourceTypeProvider, sourceFileGrouping)); }
public async Task RestoreAsync(string inputPath) { var inputUri = PathHelper.FilePathToFileUrl(inputPath); var configuration = this.configurationManager.GetConfiguration(inputUri); var sourceFileGrouping = SourceFileGroupingBuilder.Build(this.fileResolver, this.moduleDispatcher, this.workspace, inputUri, configuration); var originalModulesToRestore = sourceFileGrouping.ModulesToRestore; // restore is supposed to only restore the module references that are syntactically valid await moduleDispatcher.RestoreModules(configuration, moduleDispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration)); // update the errors based on restore status sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(this.moduleDispatcher, this.workspace, sourceFileGrouping, configuration); LogDiagnostics(GetModuleRestoreDiagnosticsByBicepFile(sourceFileGrouping, originalModulesToRestore)); }
private static Compilation GetCompilation(string fileContents) { var fileUri = new Uri("inmemory:///main.bicep"); var workspace = new Workspace(); var sourceFile = SourceFileFactory.CreateSourceFile(fileUri, fileContents); workspace.UpsertSourceFile(sourceFile); var fileResolver = new FileResolver(); var dispatcher = new ModuleDispatcher(new EmptyModuleRegistryProvider()); var configurationManager = new ConfigurationManager(new IOFileSystem()); var configuration = configurationManager.GetBuiltInConfiguration(); var sourceFileGrouping = SourceFileGroupingBuilder.Build(fileResolver, dispatcher, workspace, fileUri, configuration); return(new Compilation(namespaceProvider, sourceFileGrouping, configuration)); }
private async Task <string> GenerateForceModulesRestoreOutputMessage(string bicepFilePath, DocumentUri documentUri) { var fileUri = documentUri.ToUri(); RootConfiguration?configuration = null; try { configuration = this.configurationManager.GetConfiguration(fileUri); } catch (ConfigurationException exception) { // Fail the restore if there's configuration errors. return(exception.Message); } Workspace workspace = new Workspace(); SourceFileGrouping sourceFileGrouping = SourceFileGroupingBuilder.Build(this.fileResolver, this.moduleDispatcher, workspace, fileUri, configuration); // Ignore modules to restore logic, include all modules to be restored var modulesToRestore = sourceFileGrouping.SourceFilesByModuleDeclaration .Select(kvp => kvp.Key) .Union(sourceFileGrouping.ModulesToRestore) .ToImmutableHashSet(); // RestoreModules() does a distinct but we'll do it also to prevent deuplicates in outputs and logging var modulesToRestoreReferences = this.moduleDispatcher.GetValidModuleReferences(modulesToRestore, configuration) .Distinct() .OrderBy(key => key.FullyQualifiedReference); if (!modulesToRestoreReferences.Any()) { return($"Restore (force) skipped. No modules references in input file."); } // restore is supposed to only restore the module references that are syntactically valid await this.moduleDispatcher.RestoreModules(configuration, modulesToRestoreReferences, forceModulesRestore : true); // if all are marked as success var sbRestoreSummary = new StringBuilder(); foreach (var module in modulesToRestoreReferences) { var restoreStatus = this.moduleDispatcher.GetModuleRestoreStatus(module, configuration, out _); sbRestoreSummary.Append($"{Environment.NewLine} * {module.FullyQualifiedReference}: {restoreStatus}"); } return($"Restore (force) summary: {sbRestoreSummary}"); }
public Compilation Compile(string inputPath) { var inputUri = PathHelper.FilePathToFileUrl(inputPath); var sourceFileGrouping = SourceFileGroupingBuilder.Build(this.fileResolver, this.moduleDispatcher, this.workspace, inputUri); if (moduleDispatcher.RestoreModules(sourceFileGrouping.ModulesToRestore)) { // modules had to be restored - recompile sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(moduleDispatcher, new Workspace(), sourceFileGrouping); } var compilation = new Compilation(this.invocationContext.ResourceTypeProvider, sourceFileGrouping); LogDiagnostics(compilation); return(compilation); }
protected static IEnumerable <string> GetAllDiagnostics(string bicepFilePath) { var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver)); var sourceFileGrouping = SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, new Workspace(), PathHelper.FilePathToFileUrl(bicepFilePath)); var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), sourceFileGrouping); var output = new List <string>(); foreach (var(bicepFile, diagnostics) in compilation.GetAllDiagnosticsByBicepFile()) { foreach (var diagnostic in diagnostics) { var(line, character) = TextCoordinateConverter.GetPosition(bicepFile.LineStarts, diagnostic.Span.Position); var codeDescription = diagnostic.Uri == null ? string.Empty : $" [{diagnostic.Uri.AbsoluteUri}]"; output.Add($"{bicepFile.FileUri.LocalPath}({line + 1},{character + 1}) : {diagnostic.Level} {diagnostic.Code}: {diagnostic.Message}{codeDescription}"); } } return(output); }
public static SourceFileGrouping CreateForFiles(IReadOnlyDictionary <Uri, string> fileContentsByUri, Uri entryFileUri, IFileResolver fileResolver, RootConfiguration configuration, IFeatureProvider?features = null) { features ??= BicepTestConstants.Features; var workspace = new Workspace(); var sourceFiles = fileContentsByUri.Select(kvp => SourceFileFactory.CreateSourceFile(kvp.Key, kvp.Value)); workspace.UpsertSourceFiles(sourceFiles); return(SourceFileGroupingBuilder.Build( fileResolver, new ModuleDispatcher( new DefaultModuleRegistryProvider( fileResolver, BicepTestConstants.ClientFactory, BicepTestConstants.TemplateSpecRepositoryFactory, features)), workspace, entryFileUri, configuration)); }
public async Task RestoreAsync(string inputPath, bool forceModulesRestore) { var inputUri = PathHelper.FilePathToFileUrl(inputPath); var configuration = this.configurationManager.GetConfiguration(inputUri); var sourceFileGrouping = SourceFileGroupingBuilder.Build(this.fileResolver, this.moduleDispatcher, this.workspace, inputUri, configuration, forceModulesRestore); var originalModulesToRestore = sourceFileGrouping.ModulesToRestore; // RestoreModules() does a distinct but we'll do it also to prevent duplicates in processing and logging var modulesToRestoreReferences = this.moduleDispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration) .Distinct() .OrderBy(key => key.FullyQualifiedReference); // restore is supposed to only restore the module references that are syntactically valid await moduleDispatcher.RestoreModules(configuration, modulesToRestoreReferences, forceModulesRestore); // update the errors based on restore status sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(this.moduleDispatcher, this.workspace, sourceFileGrouping, configuration); LogDiagnostics(GetModuleRestoreDiagnosticsByBicepFile(sourceFileGrouping, originalModulesToRestore, forceModulesRestore)); }
public void ValidBicep_TemplateEmiterShouldProduceExpectedTemplate(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var compiledFilePath = FileHelper.GetResultFilePath(this.TestContext, Path.Combine(dataSet.Name, DataSet.TestFileMainCompiled)); // emitting the template should be successful var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver)); var result = this.EmitTemplate(SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, new Workspace(), PathHelper.FilePathToFileUrl(bicepFilePath)), compiledFilePath, BicepTestConstants.DevAssemblyFileVersion); result.Diagnostics.Should().NotHaveErrors(); result.Status.Should().Be(EmitStatus.Succeeded); var actual = JToken.Parse(File.ReadAllText(compiledFilePath)); actual.Should().EqualWithJsonDiffOutput( TestContext, JToken.Parse(dataSet.Compiled !), expectedLocation: DataSet.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainCompiled), actualLocation: compiledFilePath); }
public static async Task <(Compilation compilation, string outputDirectory, Uri fileUri)> SetupPrerequisitesAndCreateCompilation(this DataSet dataSet, TestContext testContext) { var features = BicepTestConstants.CreateFeaturesProvider(testContext, registryEnabled: dataSet.HasExternalModules); var outputDirectory = dataSet.SaveFilesToTestDirectory(testContext); var clientFactory = dataSet.CreateMockRegistryClients(testContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, testContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(testContext); var fileUri = PathHelper.FilePathToFileUrl(Path.Combine(outputDirectory, DataSet.TestFileMain)); var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver, clientFactory, templateSpecRepositoryFactory, features)); var workspace = new Workspace(); var namespaceProvider = new DefaultNamespaceProvider(new AzResourceTypeLoader(), features); var configuration = BicepTestConstants.ConfigurationManager.GetConfiguration(fileUri); var sourceFileGrouping = SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, workspace, fileUri, configuration); if (await dispatcher.RestoreModules(configuration, dispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration))) { sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(dispatcher, workspace, sourceFileGrouping, configuration); } return(new Compilation(namespaceProvider, sourceFileGrouping, configuration, new LinterAnalyzer(configuration)), outputDirectory, fileUri); }
public async Task ValidBicep_EmitTemplate_should_produce_expected_symbolicname_template(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var clientFactory = dataSet.CreateMockRegistryClients(TestContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var bicepFileUri = PathHelper.FilePathToFileUrl(bicepFilePath); var compiledFilePath = FileHelper.GetResultFilePath(this.TestContext, Path.Combine(dataSet.Name, DataSet.TestFileMainCompiledWithSymbolicNames)); var configuration = BicepTestConstants.ConfigurationManager.GetConfiguration(bicepFileUri); // emitting the template should be successful var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver, clientFactory, templateSpecRepositoryFactory, BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: dataSet.HasRegistryModules))); Workspace workspace = new(); var sourceFileGrouping = SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, workspace, bicepFileUri, configuration); if (await dispatcher.RestoreModules(configuration, dispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration))) { sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(dispatcher, workspace, sourceFileGrouping, configuration); } var result = this.EmitTemplate(sourceFileGrouping, BicepTestConstants.EmitterSettingsWithSymbolicNames, compiledFilePath); result.Diagnostics.Should().NotHaveErrors(); result.Status.Should().Be(EmitStatus.Succeeded); var outputFile = File.ReadAllText(compiledFilePath); var actual = JToken.Parse(outputFile); actual.Should().EqualWithJsonDiffOutput( TestContext, JToken.Parse(dataSet.CompiledWithSymbolicNames !), expectedLocation: DataSet.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainCompiledWithSymbolicNames), actualLocation: compiledFilePath); // validate that the template is parseable by the deployment engine TemplateHelper.TemplateShouldBeValid(outputFile); }
public async Task ValidBicepTextWriter_TemplateEmiterShouldProduceExpectedTemplate(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var clientFactory = dataSet.CreateMockRegistryClients(TestContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var bicepFileUri = PathHelper.FilePathToFileUrl(bicepFilePath); MemoryStream memoryStream = new MemoryStream(); // emitting the template should be successful var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver, clientFactory, templateSpecRepositoryFactory, BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: dataSet.HasExternalModules))); var workspace = new Workspace(); var configuration = BicepTestConstants.ConfigurationManager.GetConfiguration(bicepFileUri); var sourceFileGrouping = SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, workspace, PathHelper.FilePathToFileUrl(bicepFilePath), configuration); if (await dispatcher.RestoreModules(configuration, dispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration))) { sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(dispatcher, workspace, sourceFileGrouping, configuration); } var result = this.EmitTemplate(sourceFileGrouping, BicepTestConstants.EmitterSettings, memoryStream); result.Diagnostics.Should().NotHaveErrors(); result.Status.Should().Be(EmitStatus.Succeeded); // normalizing the formatting in case there are differences in indentation // this way the diff between actual and expected will be clean var actual = JToken.ReadFrom(new JsonTextReader(new StreamReader(new MemoryStream(memoryStream.ToArray())))); var compiledFilePath = FileHelper.SaveResultFile(this.TestContext, Path.Combine(dataSet.Name, DataSet.TestFileMainCompiled), actual.ToString(Formatting.Indented)); actual.Should().EqualWithJsonDiffOutput( TestContext, JToken.Parse(dataSet.Compiled !), expectedLocation: DataSet.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainCompiled), actualLocation: compiledFilePath); }
public CompilationContext Update(IReadOnlyWorkspace workspace, CompilationContext current, ImmutableDictionary <ISourceFile, ISemanticModel> modelLookup) { var syntaxTreeGrouping = SourceFileGroupingBuilder.Rebuild(moduleDispatcher, workspace, current.Compilation.SourceFileGrouping); return(this.CreateContext(syntaxTreeGrouping, modelLookup)); }
public CompilationContext Create(IReadOnlyWorkspace workspace, DocumentUri documentUri, ImmutableDictionary <ISourceFile, ISemanticModel> modelLookup) { var syntaxTreeGrouping = SourceFileGroupingBuilder.Build(fileResolver, moduleDispatcher, workspace, documentUri.ToUri()); return(this.CreateContext(syntaxTreeGrouping, modelLookup)); }
public async Task InvalidRootCachePathShouldProduceReasonableErrors() { var dataSet = DataSets.Registry_LF; var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var clientFactory = dataSet.CreateMockRegistryClients(TestContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext); var fileUri = PathHelper.FilePathToFileUrl(Path.Combine(outputDirectory, DataSet.TestFileMain)); var badCacheDirectory = FileHelper.GetCacheRootPath(TestContext); Directory.CreateDirectory(badCacheDirectory); var badCachePath = Path.Combine(badCacheDirectory, "file.txt"); File.Create(badCachePath); File.Exists(badCachePath).Should().BeTrue(); // cache root points to a file var features = new Mock <IFeatureProvider>(MockBehavior.Strict); features.Setup(m => m.RegistryEnabled).Returns(true); features.SetupGet(m => m.CacheRootDirectory).Returns(badCachePath); var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver, clientFactory, templateSpecRepositoryFactory, features.Object)); var workspace = new Workspace(); var configuration = BicepTestConstants.ConfigurationManager.GetConfiguration(fileUri); var sourceFileGrouping = SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, workspace, fileUri, configuration); if (await dispatcher.RestoreModules(configuration, dispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration))) { sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(dispatcher, workspace, sourceFileGrouping, configuration); } var compilation = new Compilation(BicepTestConstants.Features, BicepTestConstants.NamespaceProvider, sourceFileGrouping, configuration, BicepTestConstants.LinterAnalyzer); var diagnostics = compilation.GetAllDiagnosticsByBicepFile(); diagnostics.Should().HaveCount(1); diagnostics.Single().Value.ExcludingLinterDiagnostics().Should().SatisfyRespectively( x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"br:mock-registry-one.invalid/demo/plan:v2\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"br:mock-registry-one.invalid/demo/plan:v2\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"br:mock-registry-two.invalid/demo/site:v3\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"br:mock-registry-two.invalid/demo/site:v3\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"ts:00000000-0000-0000-0000-000000000000/test-rg/storage-spec:1.0\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"ts:00000000-0000-0000-0000-000000000000/test-rg/storage-spec:1.0\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"ts:11111111-1111-1111-1111-111111111111/prod-rg/vnet-spec:v2\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP062"); x.Message.Should().Be("The referenced declaration with name \"siteDeploy\" is not valid."); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"br:localhost:5000/passthrough/port:v1\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"br:127.0.0.1/passthrough/ipv4:v1\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"br:127.0.0.1:5000/passthrough/ipv4port:v1\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"br:[::1]/passthrough/ipv6:v1\": Unable to create the local module directory \""); }, x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP192"); x.Message.Should().StartWith("Unable to restore the module with reference \"br:[::1]:5000/passthrough/ipv6port:v1\": Unable to create the local module directory \""); }); }