Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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));
        }
Esempio n. 6
0
        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));
        }
Esempio n. 7
0
        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));
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        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));
        }
Esempio n. 12
0
        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));
        }
Esempio n. 13
0
        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}");
        }
Esempio n. 15
0
        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);
        }
Esempio n. 16
0
        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));
        }
Esempio n. 18
0
        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));
        }
Esempio n. 19
0
        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);
        }
Esempio n. 21
0
        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);
        }
Esempio n. 22
0
        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);
        }
Esempio n. 23
0
        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));
        }
Esempio n. 24
0
        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));
        }
Esempio n. 25
0
        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 \"");
            });
        }