public void VerifySnippetTemplatesAreErrorFree(CompletionData completionData)
        {
            string pathPrefix = $"Completions/SnippetTemplates/{completionData.Prefix}";

            var outputDirectory = FileHelper.SaveEmbeddedResourcesWithPathPrefix(TestContext, typeof(SnippetTemplatesTests).Assembly, pathPrefix);

            var mainUri       = PathHelper.FilePathToFileUrl(Path.Combine(outputDirectory, "main.bicep"));
            var bicepContents = completionData.SnippetText;
            var files         = new Dictionary <Uri, string>
            {
                [mainUri] = bicepContents,
            };
            var prefix = completionData.Prefix;

            // Template - module.bicep requires a path. So we'll create param.bicep file and
            // specify it in module snippet template
            if (prefix == "module")
            {
                var paramUri = PathHelper.FilePathToFileUrl(Path.Combine(outputDirectory, "param.bicep"));
                files.Add(paramUri, "param myParam string = 'test'");
            }

            var compilation   = new Compilation(TestTypeHelper.CreateEmptyProvider(), SourceFileGroupingFactory.CreateForFiles(files, mainUri, BicepTestConstants.FileResolver));
            var semanticModel = compilation.GetEntrypointSemanticModel();

            if (semanticModel.HasErrors())
            {
                var errors = semanticModel.GetAllDiagnostics().Where(x => x.Level == DiagnosticLevel.Error);
                var sourceTextWithDiags = OutputHelper.AddDiagsToSourceText(bicepContents, "\n", errors, diag => OutputHelper.GetDiagLoggingString(bicepContents, outputDirectory, diag));
                Assert.Fail("Template with prefix {0} contains errors. Please fix following errors:\n {1}", completionData.Prefix, sourceTextWithDiags);
            }
        }
示例#2
0
        public void ProgramsShouldProduceExpectedUserDeclaredSymbols(DataSet dataSet)
        {
            var compilation = dataSet.CopyFilesAndCreateCompilation(TestContext, out var outputDirectory);
            var model       = compilation.GetEntrypointSemanticModel();

            var symbols = SymbolCollector
                          .CollectSymbols(model)
                          .OfType <DeclaredSymbol>();

            var lineStarts = compilation.SyntaxTreeGrouping.EntryPoint.LineStarts;

            string getLoggingString(DeclaredSymbol symbol)
            {
                (_, var startChar) = TextCoordinateConverter.GetPosition(lineStarts, symbol.DeclaringSyntax.Span.Position);

                return($"{symbol.Kind} {symbol.Name}. Type: {symbol.Type}. Declaration start char: {startChar}, length: {symbol.DeclaringSyntax.Span.Length}");
            }

            var sourceTextWithDiags = OutputHelper.AddDiagsToSourceText(dataSet, symbols, symb => symb.NameSyntax.Span, getLoggingString);
            var resultsFile         = Path.Combine(outputDirectory, DataSet.TestFileMainDiagnostics);

            File.WriteAllText(resultsFile, sourceTextWithDiags);

            sourceTextWithDiags.Should().EqualWithLineByLineDiffOutput(
                dataSet.Symbols,
                expectedLocation: OutputHelper.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainSymbols),
                actualLocation: resultsFile);
        }
示例#3
0
        public void ProgramsShouldProduceExpectedUserDeclaredSymbols(DataSet dataSet)
        {
            var compilation = new Compilation(TestResourceTypeProvider.CreateRegistrar(), SyntaxFactory.CreateFromText(dataSet.Bicep));
            var model       = compilation.GetSemanticModel();

            var symbols = SymbolCollector
                          .CollectSymbols(model)
                          .OfType <DeclaredSymbol>();

            var lineStarts = TextCoordinateConverter.GetLineStarts(dataSet.Bicep);

            string getLoggingString(DeclaredSymbol symbol)
            {
                (_, var startChar) = TextCoordinateConverter.GetPosition(lineStarts, symbol.DeclaringSyntax.Span.Position);

                return($"{symbol.Kind} {symbol.Name}. Type: {symbol.Type}. Declaration start char: {startChar}, length: {symbol.DeclaringSyntax.Span.Length}");
            }

            var sourceTextWithDiags = OutputHelper.AddDiagsToSourceText(dataSet, symbols, symb => symb.NameSyntax.Span, getLoggingString);
            var resultsFile         = FileHelper.SaveResultFile(this.TestContext !, Path.Combine(dataSet.Name, DataSet.TestFileMainSymbols), sourceTextWithDiags);

            sourceTextWithDiags.Should().EqualWithLineByLineDiffOutput(
                dataSet.Symbols,
                expectedLocation: OutputHelper.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainSymbols),
                actualLocation: resultsFile);
        }
示例#4
0
        public async Task ValidateSnippetCompletionAfterPlaceholderReplacements(CompletionData completionData)
        {
            string pathPrefix = $"Completions/SnippetTemplates/{completionData.Prefix}";

            var outputDirectory = FileHelper.SaveEmbeddedResourcesWithPathPrefix(TestContext, typeof(CompletionTests).Assembly, pathPrefix);

            var bicepFileName       = Path.Combine(outputDirectory, "main.bicep");
            var bicepSourceFileName = Path.Combine("src", "Bicep.LangServer.IntegrationTests", pathPrefix, Path.GetRelativePath(outputDirectory, bicepFileName));

            File.Exists(bicepFileName).Should().BeTrue($"Snippet placeholder file \"{bicepSourceFileName}\" should be checked in");

            var bicepContents = await File.ReadAllTextAsync(bicepFileName);

            bicepContents = StringUtils.ReplaceNewlines(bicepContents, "\n");
            var cursor = bicepContents.IndexOf("// Insert snippet here");

            // Request the expected completion from the server, and ensure it is unique + valid
            var completionText = await RequestSnippetCompletion(bicepFileName, completionData, bicepContents, cursor);

            // Replace all the placeholders with values from the placeholder file
            var replacementContents = SnippetCompletionTestHelper.GetSnippetTextAfterPlaceholderReplacements(completionText, bicepContents);

            var bicepContentsReplaced = bicepContents.Substring(0, cursor) +
                                        replacementContents +
                                        bicepContents.Substring(cursor);

            using (new AssertionScope())
            {
                var combinedFileName       = Path.Combine(outputDirectory, "main.combined.bicep");
                var combinedSourceFileName = Path.Combine("src", "Bicep.LangServer.IntegrationTests", pathPrefix, Path.GetRelativePath(outputDirectory, combinedFileName));
                File.Exists(combinedFileName).Should().BeTrue($"Combined snippet file \"{combinedSourceFileName}\" should be checked in");

                var combinedFileUri    = PathHelper.FilePathToFileUrl(combinedFileName);
                var sourceFileGrouping = SourceFileGroupingFactory.CreateForFiles(new Dictionary <Uri, string>
                {
                    [combinedFileUri] = bicepContentsReplaced,
                }, combinedFileUri, BicepTestConstants.FileResolver);
                var compilation = new Compilation(TypeProvider, sourceFileGrouping);
                var diagnostics = compilation.GetEntrypointSemanticModel().GetAllDiagnostics();

                var sourceTextWithDiags = OutputHelper.AddDiagsToSourceText(bicepContentsReplaced, "\n", diagnostics, diag => OutputHelper.GetDiagLoggingString(bicepContentsReplaced, outputDirectory, diag));
                File.WriteAllText(combinedFileName + ".actual", sourceTextWithDiags);

                if (diagnostics.Any())
                {
                    Execute.Assertion.FailWith(
                        "Expected {0} file to not contain errors or warnings, but found {1}. Please fix errors/warnings mentioned in below section in {0} file:\n {2}",
                        "main.combined.bicep",
                        diagnostics.Count(),
                        sourceTextWithDiags);
                }

                sourceTextWithDiags.Should().EqualWithLineByLineDiffOutput(
                    TestContext,
                    File.Exists(combinedFileName) ? (await File.ReadAllTextAsync(combinedFileName)) : string.Empty,
                    expectedLocation: combinedSourceFileName,
                    actualLocation: combinedFileName + ".actual");
            }
        }
示例#5
0
        public void ProgramsShouldProduceExpectedDiagnostics(DataSet dataSet)
        {
            var compilation = new Compilation(TestResourceTypeProvider.CreateRegistrar(), SyntaxFactory.CreateFromText(dataSet.Bicep));
            var model       = compilation.GetSemanticModel();

            string getLoggingString(Diagnostic diagnostic)
            {
                var spanText = OutputHelper.GetSpanText(dataSet.Bicep, diagnostic);

                return($"[{diagnostic.Code} ({diagnostic.Level})] {diagnostic.Message} |{spanText}|");
            }

            var sourceTextWithDiags = OutputHelper.AddDiagsToSourceText(dataSet, model.GetAllDiagnostics(), getLoggingString);
            var resultsFile         = FileHelper.SaveResultFile(this.TestContext !, Path.Combine(dataSet.Name, DataSet.TestFileMainDiagnostics), sourceTextWithDiags);

            sourceTextWithDiags.Should().EqualWithLineByLineDiffOutput(
                dataSet.Diagnostics,
                expectedLocation: OutputHelper.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainDiagnostics),
                actualLocation: resultsFile);
        }
示例#6
0
        public async Task ValidateSnippetCompletionAfterPlaceholderReplacements(CompletionData completionData)
        {
            string pathPrefix = $"Completions/SnippetTemplates/{completionData.Prefix}";

            var outputDirectory = FileHelper.SaveEmbeddedResourcesWithPathPrefix(TestContext, typeof(CompletionTests).Assembly, pathPrefix);

            var bicepFileName       = Path.Combine(outputDirectory, "main.bicep");
            var bicepSourceFileName = Path.Combine("src", "Bicep.LangServer.IntegrationTests", pathPrefix, Path.GetRelativePath(outputDirectory, bicepFileName));

            File.Exists(bicepFileName).Should().BeTrue($"Snippet placeholder file \"{bicepSourceFileName}\" should be checked in");
            var bicepContents = await File.ReadAllTextAsync(bicepFileName);

            // Request the expected completion from the server, and ensure it is unique + valid
            var completionText = await RequestSnippetCompletion(bicepFileName, completionData, bicepContents);

            // Replace all the placeholders with values from the placeholder file
            var replacementContents = SnippetCompletionTestHelper.GetSnippetTextAfterPlaceholderReplacements(completionText, bicepContents);

            using (new AssertionScope())
            {
                var combinedFileName       = Path.Combine(outputDirectory, "main.combined.bicep");
                var combinedSourceFileName = Path.Combine("src", "Bicep.LangServer.IntegrationTests", pathPrefix, Path.GetRelativePath(outputDirectory, combinedFileName));
                File.Exists(combinedFileName).Should().BeTrue($"Combined snippet file \"{combinedSourceFileName}\" should be checked in");

                var syntaxTreeGrouping = SyntaxTreeGroupingBuilder.Build(new FileResolver(), new Workspace(), PathHelper.FilePathToFileUrl(combinedFileName));
                var compilation        = new Compilation(TypeProvider, syntaxTreeGrouping);
                var diagnostics        = compilation.GetEntrypointSemanticModel().GetAllDiagnostics();

                var sourceTextWithDiags = OutputHelper.AddDiagsToSourceText(replacementContents, Environment.NewLine, diagnostics, diag => OutputHelper.GetDiagLoggingString(replacementContents, outputDirectory, diag));
                File.WriteAllText(combinedFileName + ".actual", sourceTextWithDiags);

                sourceTextWithDiags.Should().EqualWithLineByLineDiffOutput(
                    TestContext,
                    File.Exists(combinedFileName) ? (await File.ReadAllTextAsync(combinedFileName)) : string.Empty,
                    expectedLocation: combinedSourceFileName,
                    actualLocation: combinedFileName + ".actual");
            }
        }
示例#7
0
        public void ProgramsShouldProduceExpectedDiagnostics(DataSet dataSet)
        {
            var compilation = dataSet.CopyFilesAndCreateCompilation(TestContext, out var outputDirectory);
            var model       = compilation.GetEntrypointSemanticModel();

            string getLoggingString(Diagnostic diagnostic)
            {
                var spanText = OutputHelper.GetSpanText(dataSet.Bicep, diagnostic);
                var message  = diagnostic.Message.Replace($"{outputDirectory}{Path.DirectorySeparatorChar}", "${TEST_OUTPUT_DIR}");

                return($"[{diagnostic.Code} ({diagnostic.Level})] {message} |{spanText}|");
            }

            var sourceTextWithDiags = OutputHelper.AddDiagsToSourceText(dataSet, model.GetAllDiagnostics(), getLoggingString);
            var resultsFile         = Path.Combine(outputDirectory, DataSet.TestFileMainDiagnostics);

            File.WriteAllText(resultsFile, sourceTextWithDiags);

            sourceTextWithDiags.Should().EqualWithLineByLineDiffOutput(
                dataSet.Diagnostics,
                expectedLocation: OutputHelper.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainDiagnostics),
                actualLocation: resultsFile);
        }
示例#8
0
        public void VerifySnippetTemplatesAreErrorFree(CompletionData completionData)
        {
            string pathPrefix = $"Completions/SnippetTemplates/{completionData.Prefix}";

            var outputDirectory = FileHelper.SaveEmbeddedResourcesWithPathPrefix(TestContext, typeof(SnippetTemplatesTests).Assembly, pathPrefix);

            var mainUri       = PathHelper.FilePathToFileUrl(Path.Combine(outputDirectory, "main.bicep"));
            var bicepContents = completionData.SnippetText;
            var files         = new Dictionary <Uri, string>
            {
                [mainUri] = bicepContents,
            };

            // overrides for certain snippets which have contextual dependencies (e.g. external files)
            switch (completionData.Prefix)
            {
            case "module":
                var paramUri = PathHelper.FilePathToFileUrl(Path.Combine(outputDirectory, "param.bicep"));
                files.Add(paramUri, "param myParam string = 'test'");
                break;

            case "res-logic-app-from-file":
                var requiredFile = PathHelper.FilePathToFileUrl(Path.Combine(outputDirectory, "REQUIRED"));
                files.Add(requiredFile, @"{""definition"":{""$schema"":""https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#"",""contentVersion"":""1.0.0.0"",""outputs"":{}}}");
                return;
            }

            var compilation   = new Compilation(TestTypeHelper.CreateEmptyProvider(), SourceFileGroupingFactory.CreateForFiles(files, mainUri, BicepTestConstants.FileResolver, BicepTestConstants.BuiltInConfiguration), BicepTestConstants.BuiltInConfiguration);
            var semanticModel = compilation.GetEntrypointSemanticModel();

            if (semanticModel.HasErrors())
            {
                var errors = semanticModel.GetAllDiagnostics().Where(x => x.Level == DiagnosticLevel.Error);
                var sourceTextWithDiags = OutputHelper.AddDiagsToSourceText(bicepContents, "\n", errors, diag => OutputHelper.GetDiagLoggingString(bicepContents, outputDirectory, diag));
                Assert.Fail("Template with prefix {0} contains errors. Please fix following errors:\n {1}", completionData.Prefix, sourceTextWithDiags);
            }
        }
示例#9
0
文件: DataSet.cs 项目: rynowak/bicep
 public static string AddDiagsToSourceText <TPositionable>(DataSet dataSet, IEnumerable <TPositionable> items, Func <TPositionable, string> diagsFunc)
     where TPositionable : IPositionable
 => OutputHelper.AddDiagsToSourceText(dataSet.Bicep, dataSet.HasCrLfNewlines() ? "\r\n" : "\n", items, item => item.Span, diagsFunc);
示例#10
0
文件: DataSet.cs 项目: rynowak/bicep
 public static string AddDiagsToSourceText <T>(DataSet dataSet, IEnumerable <T> items, Func <T, TextSpan> getSpanFunc, Func <T, string> diagsFunc)
 => OutputHelper.AddDiagsToSourceText <T>(dataSet.Bicep, dataSet.HasCrLfNewlines() ? "\r\n" : "\n", items, getSpanFunc, diagsFunc);