예제 #1
0
        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[] {
예제 #2
0
        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();
        }
예제 #4
0
        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();
        }
예제 #5
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,
            };
            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);
            }
        }
예제 #6
0
        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);
        }
예제 #7
0
        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[] {
예제 #8
0
 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);
     }));
 }
예제 #9
0
        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));
        }
예제 #10
0
        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();
        }
예제 #11
0
        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));
        }
예제 #12
0
        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));
        }
예제 #13
0
        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();
        }
예제 #14
0
        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));
        }
예제 #15
0
        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);
        }
예제 #16
0
        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();
        }
예제 #18
0
        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);
        }
예제 #20
0
        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);
        }
예제 #25
0
        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);
        }
예제 #26
0
        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);
        }
예제 #27
0
        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);
        }
예제 #28
0
        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);
        }
예제 #29
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);
        }
예제 #30
0
        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);
        }