public void Module_self_cycle_is_detected_correctly() { var mainUri = new Uri("file:///main.bicep"); var files = new Dictionary <Uri, string> { [mainUri] = @" param inputa string param inputb string module mainRecursive 'main.bicep' = { name: 'mainRecursive' params: { inputa: inputa inputb: inputb } } ", }; var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), SourceFileGroupingFactory.CreateForFiles(files, mainUri, BicepTestConstants.FileResolver, Configuration), Configuration, LinterAnalyzer); var(success, diagnosticsByFile) = GetSuccessAndDiagnosticsByFile(compilation); diagnosticsByFile[mainUri].Should().HaveDiagnostics(new[] {
public void NestedResources_invalid_resource_references() { var program = @" var notResource = 'hi' resource parent 'My.RP/parentType@2020-01-01' = { name: 'parent' properties: { size: 'large' } resource child 'childType' = { name: 'child' properties: { style: 'very cool' } resource grandchild 'grandchildType' = { name: 'grandchild' properties: { temperature: 'ice-cold' } } } } output fromVariable string = notResource::child.properties.style output fromChildInvalid string = parent::child2.properties.style output fromGrandchildInvalid string = parent::child::cousin.properties.temperature "; var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), SyntaxTreeGroupingFactory.CreateFromText(program)); var model = compilation.GetEntrypointSemanticModel(); model.GetAllDiagnostics().Should().HaveDiagnostics(new [] {
public void CompletionsForOneLinerParameterDefaultValueShouldIncludeFunctionsValidInDefaultValues() { var grouping = SyntaxTreeGroupingFactory.CreateFromText(@"param p string = "); var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), grouping); var offset = ((ParameterDefaultValueSyntax)grouping.EntryPoint.ProgramSyntax.Declarations.OfType <ParameterDeclarationSyntax>().Single().Modifier !).DefaultValue.Span.Position; var provider = new BicepCompletionProvider(new FileResolver(), new SnippetsProvider(), new TelemetryProvider(Server)); var completions = provider.GetFilteredCompletions( compilation, BicepCompletionContext.Create(compilation, offset)).ToList(); AssertExpectedFunctions(completions, expectParamDefaultFunctions: true); // outputs can't be referenced so they should not show up in completions completions.Where(c => c.Kind == SymbolKind.Output.ToCompletionItemKind()).Should().BeEmpty(); completions.Where(c => c.Kind == SymbolKind.Variable.ToCompletionItemKind()).Should().BeEmpty(); completions.Where(c => c.Kind == SymbolKind.Resource.ToCompletionItemKind()).Should().BeEmpty(); completions.Where(c => c.Kind == SymbolKind.Module.ToCompletionItemKind()).Should().BeEmpty(); // should not see parameter completions because we set the enclosing declaration which will exclude the corresponding symbol // this avoids cycle suggestions completions.Where(c => c.Kind == SymbolKind.Parameter.ToCompletionItemKind()).Should().BeEmpty(); }
public void LockedModeShouldBlockAccess() { const string expectedMessage = "Properties of the symbol context should not be accessed until name binding is completed."; var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), SyntaxTreeGroupingFactory.CreateFromText("")); var bindings = new Dictionary <SyntaxBase, Symbol>(); var cyclesBySymbol = new Dictionary <DeclaredSymbol, ImmutableArray <DeclaredSymbol> >(); var context = new SymbolContext(compilation, compilation.GetEntrypointSemanticModel()); Action byName = () => { var tm = context.TypeManager; }; byName.Should().Throw <InvalidOperationException>().WithMessage(expectedMessage); Action byNode = () => { var b = context.Compilation; }; byNode.Should().Throw <InvalidOperationException>().WithMessage(expectedMessage); context.Unlock(); context.TypeManager.Should().NotBeNull(); context.Compilation.Should().NotBeNull(); }
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); } }
public static async Task <ILanguageClient> StartServerWithClientConnectionAsync(Action <LanguageClientOptions> onClientOptions, IResourceTypeProvider?resourceTypeProvider = null, IFileResolver?fileResolver = null) { resourceTypeProvider ??= TestTypeHelper.CreateEmptyProvider(); fileResolver ??= new InMemoryFileResolver(new Dictionary <Uri, string>()); var clientPipe = new Pipe(); var serverPipe = new Pipe(); var server = new Server( serverPipe.Reader, clientPipe.Writer, new Server.CreationOptions { ResourceTypeProvider = resourceTypeProvider, FileResolver = fileResolver, }); var _ = server.RunAsync(CancellationToken.None); // do not wait on this async method, or you'll be waiting a long time! var client = LanguageClient.PreInit(options => { options .WithInput(clientPipe.Reader) .WithOutput(serverPipe.Writer); onClientOptions(options); }); await client.Initialize(CancellationToken.None); return(client); }
public void NestedResources_invalid_resource_references() { var program = @" var notResource = 'hi' resource parent 'My.RP/parentType@2020-01-01' = { name: 'parent' properties: { size: 'large' } resource child 'childType' = { name: 'child' properties: { style: 'very cool' } resource grandchild 'grandchildType' = { name: 'grandchild' properties: { temperature: 'ice-cold' } } } } output fromVariable string = notResource::child.properties.style output fromChildInvalid string = parent::child2.properties.style output fromGrandchildInvalid string = parent::child::cousin.properties.temperature "; var compilation = new Compilation(BicepTestConstants.Features, TestTypeHelper.CreateEmptyProvider(), SourceFileGroupingFactory.CreateFromText(program, BicepTestConstants.FileResolver), BicepTestConstants.BuiltInConfiguration, BicepTestConstants.LinterAnalyzer); var model = compilation.GetEntrypointSemanticModel(); model.GetAllDiagnostics().ExcludingLinterDiagnostics().ExcludingMissingTypes().Should().HaveDiagnostics(new[] {
protected static (string output, string error, int result) Bicep(params string[] args) { return(TextWriterHelper.InvokeWriterAction((@out, err) => { return new Program(new InvocationContext(TestTypeHelper.CreateEmptyProvider(), @out, err, BicepTestConstants.DevAssemblyFileVersion)).Run(args); })); }
private EmitResult EmitTemplate(SourceFileGrouping sourceFileGrouping, string filePath, string assemblyFileVersion) { var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), sourceFileGrouping); var emitter = new TemplateEmitter(compilation.GetEntrypointSemanticModel(), assemblyFileVersion); using var stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None); return(emitter.Emit(stream)); }
public void EmptyProgram_SyntaxTreeGrouping_should_be_persisted() { var program = SyntaxTreeGroupingFactory.CreateFromText(DataSets.Empty.Bicep); var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), program); compilation.SyntaxTreeGrouping.Should().BeSameAs(program); compilation.GetEntrypointSemanticModel().Should().NotBeNull(); }
private EmitResult EmitTemplate(SourceFileGrouping sourceFileGrouping, EmitterSettings emitterSettings, string filePath) { var compilation = new Compilation(BicepTestConstants.Features, TestTypeHelper.CreateEmptyProvider(), sourceFileGrouping, BicepTestConstants.BuiltInConfiguration, BicepTestConstants.LinterAnalyzer); var emitter = new TemplateEmitter(compilation.GetEntrypointSemanticModel(), emitterSettings); using var stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None); return(emitter.Emit(stream)); }
private EmitResult EmitTemplate(SourceFileGrouping sourceFileGrouping, EmitterSettings emitterSettings, MemoryStream memoryStream) { var compilation = new Compilation(BicepTestConstants.Features, TestTypeHelper.CreateEmptyProvider(), sourceFileGrouping, BicepTestConstants.BuiltInConfiguration, BicepTestConstants.LinterAnalyzer); var emitter = new TemplateEmitter(compilation.GetEntrypointSemanticModel(), emitterSettings); TextWriter tw = new StreamWriter(memoryStream); return(emitter.Emit(tw)); }
public void EmptyProgram_SourceFileGrouping_should_be_persisted() { var fileResolver = new FileResolver(); var program = SourceFileGroupingFactory.CreateFromText(DataSets.Empty.Bicep, fileResolver); var compilation = new Compilation(BicepTestConstants.Features, TestTypeHelper.CreateEmptyProvider(), program, BicepTestConstants.BuiltInConfiguration, BicepTestConstants.LinterAnalyzer); compilation.SourceFileGrouping.Should().BeSameAs(program); compilation.GetEntrypointSemanticModel().Should().NotBeNull(); }
private EmitResult EmitTemplate(SourceFileGrouping sourceFileGrouping, MemoryStream memoryStream, string assemblyFileVersion) { var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), sourceFileGrouping); var emitter = new TemplateEmitter(compilation.GetEntrypointSemanticModel(), assemblyFileVersion); TextWriter tw = new StreamWriter(memoryStream); return(emitter.Emit(tw)); }
public void Decompiler_raises_errors_for_unsupported_features(string resourcePath, string expectedMessage) { Action onDecompile = () => { var fileResolver = ReadResourceFile(resourcePath); TemplateDecompiler.DecompileFileWithModules(TestTypeHelper.CreateEmptyProvider(), fileResolver, new Uri($"file:///{resourcePath}")); }; onDecompile.Should().Throw <ConversionFailedException>().WithMessage(expectedMessage); }
public void VerifyDisableNextLineDiagnosticDirectivesCache_WithNoDisableNextLineDiagnosticDirectivesInBicepFile() { string bicepFileContents = @"param storageAccount string = 'testStorageAccount'"; var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), SourceFileGroupingFactory.CreateFromText(bicepFileContents, BicepTestConstants.FileResolver), BicepTestConstants.BuiltInConfiguration, BicepTestConstants.LinterAnalyzer); var bicepFile = compilation.GetEntrypointSemanticModel().SourceFile; var disabledDiagnosticsCache = bicepFile.DisabledDiagnosticsCache; var disableNextLineDirectiveEndPositionAndCodes = disabledDiagnosticsCache.TryGetDisabledNextLineDirective(0); disableNextLineDirectiveEndPositionAndCodes.Should().BeNull(); }
public void CommentShouldNotGiveAnyCompletions(string codeFragment) { var grouping = SyntaxTreeGroupingFactory.CreateFromText(codeFragment); var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), grouping); var provider = new BicepCompletionProvider(new FileResolver(), new SnippetsProvider(), new TelemetryProvider(Server)); var offset = codeFragment.IndexOf('|'); var completions = provider.GetFilteredCompletions(compilation, BicepCompletionContext.Create(compilation, offset)); completions.Should().BeEmpty(); }
public void Modules_can_be_compiled_successfully() { var mainUri = new Uri("file:///main.bicep"); var moduleAUri = new Uri("file:///modulea.bicep"); var moduleBUri = new Uri("file:///moduleb.bicep"); var files = new Dictionary <Uri, string> { [mainUri] = @" param inputa string param inputb string module modulea 'modulea.bicep' = { name: 'modulea' params: { inputa: inputa inputb: inputb } } module moduleb 'moduleb.bicep' = { name: 'moduleb' params: { inputa: inputa inputb: inputb } } output outputa string = modulea.outputs.outputa output outputb string = moduleb.outputs.outputb ", [moduleAUri] = @" param inputa string param inputb string output outputa string = '${inputa}-${inputb}' ", [moduleBUri] = @" param inputa string param inputb string output outputb string = '${inputa}-${inputb}' ", }; var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), SourceFileGroupingFactory.CreateForFiles(files, mainUri, BicepTestConstants.FileResolver, Configuration), Configuration, LinterAnalyzer); var(success, diagnosticsByFile) = GetSuccessAndDiagnosticsByFile(compilation); diagnosticsByFile.Values.SelectMany(x => x).Should().BeEmpty(); success.Should().BeTrue(); GetTemplate(compilation).Should().NotBeEmpty(); }
public void DeclaringSymbolWithFunctionNameShouldHideTheFunctionCompletion() { var grouping = SyntaxTreeGroupingFactory.CreateFromText(@" param concat string var resourceGroup = true resource base64 'Microsoft.Foo/foos@2020-09-01' = { name: 'foo' } output length int = "); var offset = grouping.EntryPoint.ProgramSyntax.Declarations.OfType <OutputDeclarationSyntax>().Single().Value.Span.Position; var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), grouping); var provider = new BicepCompletionProvider(new FileResolver(), new SnippetsProvider(), new TelemetryProvider(Server)); var context = BicepCompletionContext.Create(compilation, offset); var completions = provider.GetFilteredCompletions(compilation, context).ToList(); AssertExpectedFunctions(completions, expectParamDefaultFunctions: false, new[] { "sys.concat", "az.resourceGroup", "sys.base64" }); // outputs can't be referenced so they should not show up in completions completions.Where(c => c.Kind == SymbolKind.Output.ToCompletionItemKind()).Should().BeEmpty(); const string expectedVariable = "resourceGroup"; var variableCompletion = completions.Single(c => c.Kind == SymbolKind.Variable.ToCompletionItemKind()); variableCompletion.Label.Should().Be(expectedVariable); variableCompletion.Kind.Should().Be(CompletionItemKind.Variable); variableCompletion.InsertTextFormat.Should().Be(InsertTextFormat.PlainText); variableCompletion.TextEdit !.TextEdit !.NewText.Should().Be(expectedVariable); variableCompletion.CommitCharacters.Should().BeNull(); variableCompletion.Detail.Should().Be(expectedVariable); const string expectedResource = "base64"; var resourceCompletion = completions.Single(c => c.Kind == SymbolKind.Resource.ToCompletionItemKind()); resourceCompletion.Label.Should().Be(expectedResource); resourceCompletion.Kind.Should().Be(CompletionItemKind.Interface); resourceCompletion.InsertTextFormat.Should().Be(InsertTextFormat.PlainText); resourceCompletion.TextEdit !.TextEdit !.NewText.Should().Be(expectedResource); resourceCompletion.CommitCharacters.Should().BeEquivalentTo(new [] { ":", }); resourceCompletion.Detail.Should().Be(expectedResource); const string expectedParam = "concat"; var paramCompletion = completions.Single(c => c.Kind == SymbolKind.Parameter.ToCompletionItemKind()); paramCompletion.Label.Should().Be(expectedParam); paramCompletion.Kind.Should().Be(CompletionItemKind.Field); paramCompletion.InsertTextFormat.Should().Be(InsertTextFormat.PlainText); paramCompletion.TextEdit !.TextEdit !.NewText.Should().Be(expectedParam); paramCompletion.CommitCharacters.Should().BeNull(); paramCompletion.Detail.Should().Be(expectedParam); }
private static (IEnumerable <string> outputLines, IEnumerable <string> errorLines, int result) ExecuteProgram(params string[] args) { var(output, error, result) = TextWriterHelper.InvokeWriterAction((outputWriter, errorWriter) => { var program = new Program(TestTypeHelper.CreateEmptyProvider(), outputWriter, errorWriter, BicepTestConstants.DevAssemblyFileVersion); return(program.Run(args)); }); return( Regex.Split(output, "\r?\n").Where(x => x != ""), Regex.Split(error, "\r?\n").Where(x => x != ""), result); }
public void OutputTypeContextShouldReturnDeclarationTypeCompletions() { var grouping = SyntaxTreeGroupingFactory.CreateFromText("output test "); var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), grouping); var provider = new BicepCompletionProvider(new FileResolver(), new SnippetsProvider(), new TelemetryProvider(Server)); var offset = grouping.EntryPoint.ProgramSyntax.Declarations.OfType <OutputDeclarationSyntax>().Single().Type.Span.Position; var completions = provider.GetFilteredCompletions(compilation, BicepCompletionContext.Create(compilation, offset)); var declarationTypeCompletions = completions.Where(c => c.Kind == CompletionItemKind.Class).ToList(); AssertExpectedDeclarationTypeCompletions(declarationTypeCompletions); completions.Where(c => c.Kind == CompletionItemKind.Snippet).Should().BeEmpty(); }
public void VerifyParameterTypeCompletionWithPrecedingComment() { var grouping = SyntaxTreeGroupingFactory.CreateFromText("/*test*/param foo "); var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), grouping); var provider = new BicepCompletionProvider(new FileResolver(), new SnippetsProvider(), new TelemetryProvider(Server)); var offset = grouping.EntryPoint.ProgramSyntax.Declarations.OfType <ParameterDeclarationSyntax>().Single().Type.Span.Position; var completions = provider.GetFilteredCompletions(compilation, BicepCompletionContext.Create(compilation, offset)); var declarationTypeCompletions = completions.Where(c => c.Kind == CompletionItemKind.Class).ToList(); AssertExpectedDeclarationTypeCompletions(declarationTypeCompletions); completions.Where(c => c.Kind == CompletionItemKind.Snippet).Should().SatisfyRespectively( c => { c.Label.Should().Be("secureObject"); c.Kind.Should().Be(CompletionItemKind.Snippet); c.InsertTextFormat.Should().Be(InsertTextFormat.Snippet); c.TextEdit !.TextEdit !.NewText.Should().Be("object"); c.TextEdit.TextEdit.Range.Start.Line.Should().Be(0); c.TextEdit.TextEdit.Range.Start.Character.Should().Be(18); c.Detail.Should().Be("Secure object"); c.AdditionalTextEdits !.Count().Should().Be(1); c.AdditionalTextEdits !.ElementAt(0).NewText.Should().Be("@secure()\n"); c.AdditionalTextEdits !.ElementAt(0).Range.Start.Line.Should().Be(0); c.AdditionalTextEdits !.ElementAt(0).Range.Start.Character.Should().Be(8); c.AdditionalTextEdits !.ElementAt(0).Range.End.Line.Should().Be(0); c.AdditionalTextEdits !.ElementAt(0).Range.End.Character.Should().Be(8); }, c => { c.Label.Should().Be("secureString"); c.Kind.Should().Be(CompletionItemKind.Snippet); c.InsertTextFormat.Should().Be(InsertTextFormat.Snippet); c.TextEdit !.TextEdit !.NewText.Should().Be("string"); c.TextEdit.TextEdit.Range.Start.Line.Should().Be(0); c.TextEdit.TextEdit.Range.Start.Character.Should().Be(18); c.Detail.Should().Be("Secure string"); c.AdditionalTextEdits !.Count().Should().Be(1); c.AdditionalTextEdits !.ElementAt(0).NewText.Should().Be("@secure()\n"); c.AdditionalTextEdits !.ElementAt(0).Range.Start.Line.Should().Be(0); c.AdditionalTextEdits !.ElementAt(0).Range.Start.Character.Should().Be(8); c.AdditionalTextEdits !.ElementAt(0).Range.End.Line.Should().Be(0); c.AdditionalTextEdits !.ElementAt(0).Range.End.Character.Should().Be(8); }); }
public void Create_ShouldReturnValidCompilation() { var provider = new BicepCompilationProvider(TestTypeHelper.CreateEmptyProvider(), CreateEmptyFileResolver()); var fileUri = DocumentUri.Parse($"/{DataSets.Parameters_LF.Name}.bicep"); var syntaxTree = SyntaxTree.Create(fileUri.ToUri(), DataSets.Parameters_LF.Bicep); var workspace = new Workspace(); workspace.UpsertSyntaxTrees(syntaxTree.AsEnumerable()); var context = provider.Create(workspace, fileUri); context.Compilation.Should().NotBeNull(); // TOOD: remove Where when the support of modifiers is dropped. context.Compilation.GetEntrypointSemanticModel().GetAllDiagnostics().Where(d => d.Code != "BCP161").Should().BeEmpty(); context.LineStarts.Should().NotBeEmpty(); context.LineStarts[0].Should().Be(0); }
public void NonDeclarationContextShouldIncludeDeclaredSymbols() { var grouping = SyntaxTreeGroupingFactory.CreateFromText(@" param p string var v = resource r 'Microsoft.Foo/foos@2020-09-01' = { name: 'foo' } output o int = 42 "); var offset = grouping.EntryPoint.ProgramSyntax.Declarations.OfType <VariableDeclarationSyntax>().Single().Value.Span.Position; var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), grouping); var provider = new BicepCompletionProvider(new FileResolver(), new SnippetsProvider(), new TelemetryProvider(Server)); var context = BicepCompletionContext.Create(compilation, offset); var completions = provider.GetFilteredCompletions(compilation, context).ToList(); AssertExpectedFunctions(completions, expectParamDefaultFunctions: false); // outputs can't be referenced so they should not show up in completions completions.Where(c => c.Kind == SymbolKind.Output.ToCompletionItemKind()).Should().BeEmpty(); // the variable won't appear in completions because we are not suggesting cycles completions.Where(c => c.Kind == SymbolKind.Variable.ToCompletionItemKind()).Should().BeEmpty(); const string expectedResource = "r"; var resourceCompletion = completions.Single(c => c.Kind == SymbolKind.Resource.ToCompletionItemKind()); resourceCompletion.Label.Should().Be(expectedResource); resourceCompletion.Kind.Should().Be(CompletionItemKind.Interface); resourceCompletion.InsertTextFormat.Should().Be(InsertTextFormat.PlainText); resourceCompletion.TextEdit !.TextEdit !.NewText.Should().Be(expectedResource); resourceCompletion.CommitCharacters.Should().BeEquivalentTo(new[] { ":", }); resourceCompletion.Detail.Should().Be(expectedResource); const string expectedParam = "p"; var paramCompletion = completions.Single(c => c.Kind == SymbolKind.Parameter.ToCompletionItemKind()); paramCompletion.Label.Should().Be(expectedParam); paramCompletion.Kind.Should().Be(CompletionItemKind.Field); paramCompletion.InsertTextFormat.Should().Be(InsertTextFormat.PlainText); paramCompletion.TextEdit !.TextEdit !.NewText.Should().Be(expectedParam); paramCompletion.CommitCharacters.Should().BeNull(); paramCompletion.Detail.Should().Be(expectedParam); }
private static IEnumerable <string> GetAllDiagnostics(string bicepFilePath) { var syntaxTreeGrouping = SyntaxTreeGroupingBuilder.Build(new FileResolver(), new Workspace(), PathHelper.FilePathToFileUrl(bicepFilePath)); var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), syntaxTreeGrouping); var output = new List <string>(); foreach (var(syntaxTree, diagnostics) in compilation.GetAllDiagnosticsBySyntaxTree()) { foreach (var diagnostic in diagnostics) { var(line, character) = TextCoordinateConverter.GetPosition(syntaxTree.LineStarts, diagnostic.Span.Position); output.Add($"{syntaxTree.FileUri.LocalPath}({line + 1},{character + 1}) : {diagnostic.Level} {diagnostic.Code}: {diagnostic.Message}"); } } return(output); }
public void NestedResources_symbols_are_bound() { var program = @" resource parent 'My.RP/parentType@2020-01-01' = { name: 'parent' properties: { size: 'large' } resource child 'childType' = { name: 'child' properties: { style: 'very cool' } } resource sibling 'childType@2020-01-02' = { name: 'sibling' properties: { style: child.properties.style size: parent.properties.size } } } "; var compilation = new Compilation(BicepTestConstants.Features, TestTypeHelper.CreateEmptyProvider(), SourceFileGroupingFactory.CreateFromText(program, BicepTestConstants.FileResolver), BicepTestConstants.BuiltInConfiguration, BicepTestConstants.LinterAnalyzer); var model = compilation.GetEntrypointSemanticModel(); model.GetAllDiagnostics().ExcludingLinterDiagnostics().ExcludingMissingTypes().Should().BeEmpty(); var expected = new[] { new { name = "child", type = "My.RP/parentType/childType@2020-01-01", }, new { name = "parent", type = "My.RP/parentType@2020-01-01", }, new { name = "sibling", type = "My.RP/parentType/childType@2020-01-02", }, }; model.DeclaredResources.Select(x => x.Symbol) .Select(s => new { name = s.Name, type = (s.Type as ResourceType)?.TypeReference.FormatName(), }) .OrderBy(n => n.name) .Should().BeEquivalentTo(expected); }
public void NestedResources_symbols_are_bound() { var program = @" resource parent 'My.RP/parentType@2020-01-01' = { name: 'parent' properties: { size: 'large' } resource child 'childType' = { name: 'child' properties: { style: 'very cool' } } resource sibling 'childType@2020-01-02' = { name: 'sibling' properties: { style: child.properties.style size: parent.properties.size } } } "; var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), SyntaxTreeGroupingFactory.CreateFromText(program)); var model = compilation.GetEntrypointSemanticModel(); model.GetAllDiagnostics().Should().BeEmpty(); var expected = new [] { new { name = "child", type = "My.RP/parentType/childType@2020-01-01", }, new { name = "parent", type = "My.RP/parentType@2020-01-01", }, new { name = "sibling", type = "My.RP/parentType/childType@2020-01-02", }, }; model.Root.GetAllResourceDeclarations() .Select(s => new { name = s.Name, type = (s.Type as ResourceType)?.TypeReference.FormatName(), }) .OrderBy(n => n.name) .Should().BeEquivalentTo(expected); }
public void ShouldConvertExpressionsCorrectly(string text, string expected) { var programText = $"var test = {text}"; var compilation = new Compilation(TestTypeHelper.CreateEmptyProvider(), SourceFileGroupingFactory.CreateFromText(programText, BicepTestConstants.FileResolver), BicepTestConstants.BuiltInConfiguration); var programSyntax = compilation.SourceFileGrouping.EntryPoint.ProgramSyntax; var variableDeclarationSyntax = programSyntax.Children.OfType <VariableDeclarationSyntax>().First(); var converter = new ExpressionConverter(new EmitterContext(compilation.GetEntrypointSemanticModel(), BicepTestConstants.EmitterSettings)); var converted = converter.ConvertExpression(variableDeclarationSyntax.Value); var serializer = new ExpressionSerializer(new ExpressionSerializerSettings { IncludeOuterSquareBrackets = true, SingleStringHandling = ExpressionSerializerSingleStringHandling.SerializeAsString }); var actual = serializer.SerializeExpression(converted); actual.Should().Be(expected); }
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 void Create_ShouldReturnValidCompilation() { var fileUri = DocumentUri.Parse($"/{DataSets.Parameters_LF.Name}.bicep"); var fileResolver = CreateFileResolver(fileUri.ToUri(), DataSets.Parameters_LF.Bicep); var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(fileResolver)); var provider = new BicepCompilationProvider(TestTypeHelper.CreateEmptyProvider(), fileResolver, dispatcher); var sourceFile = SourceFileFactory.CreateSourceFile(fileUri.ToUri(), DataSets.Parameters_LF.Bicep); var workspace = new Workspace(); workspace.UpsertSourceFile(sourceFile); var context = provider.Create(workspace, fileUri, ImmutableDictionary <ISourceFile, ISemanticModel> .Empty); context.Compilation.Should().NotBeNull(); // TODO: remove Where when the support of modifiers is dropped. context.Compilation.GetEntrypointSemanticModel().GetAllDiagnostics(new ConfigHelper().GetDisabledLinterConfig()).Should().BeEmpty(); context.LineStarts.Should().NotBeEmpty(); context.LineStarts[0].Should().Be(0); }