public async Task BicepConfigFileModification_ShouldNotRefreshCompilation()
        {
            var(diagsListener, testOutputPath) = GetTestConfig();
            using var helper = await StartServerWithClientConnectionAsync(diagsListener);

            var client = helper.Client;

            var bicepConfigFileContents = @"{
  ""analyzers"": {
    ""core"": {
      ""verbose"": false,
      ""enabled"": true,
      ""rules"": {
        ""no-unused-params"": {
          ""level"": ""info""
        }
      }
    }
  }
}";
            var bicepFileContents       = @"param storageAccountName string = 'test'";

            var mainUri        = SaveFile("main.bicep", bicepFileContents, testOutputPath);
            var bicepConfigUri = SaveFile("bicepconfig.json", bicepConfigFileContents, testOutputPath);

            // open the main document and verify diagnostics
            {
                client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, bicepFileContents, 1));

                await VerifyDiagnosticsAsync(diagsListener,
                                             @"Parameter ""storageAccountName"" is declared but never used.",
                                             mainUri,
                                             DiagnosticSeverity.Information,
                                             new Position(0, 6),
                                             new Position(0, 24),
                                             "https://aka.ms/bicep/linter/no-unused-params");
            }

            // update bicepconfig.json and verify diagnostics message is not sent
            {
                client.TextDocument.DidChangeTextDocument(TextDocumentParamHelper.CreateDidChangeTextDocumentParams(bicepConfigUri, @"{
  ""analyzers"": {
    ""core"": {
      ""verbose"": false,
      ""enabled"": true,
      ""rules"": {
        ""no-unused-params"": {
          ""level"": ""off""
        }
      }
    }
  }
}", 2));

                await diagsListener.EnsureNoMessageSent();
            }
        }
        public async Task DidOpenTextDocument_should_trigger_PublishDiagnostics()
        {
            var documentUri   = DocumentUri.From("/template.bicep");
            var diagsReceived = new TaskCompletionSource <PublishDiagnosticsParams>();

            var client = await IntegrationTestHelper.StartServerWithClientConnectionAsync(options =>
            {
                options.OnPublishDiagnostics(diags => {
                    diagsReceived.SetResult(diags);
                });
            });

            // open document
            client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(documentUri, @"
param myParam string = 2
resource myRes 'invalidFormat' = {

}
randomToken
", 1));

            var response = await IntegrationTestHelper.WithTimeoutAsync(diagsReceived.Task);

            response.Diagnostics.Should().SatisfyRespectively(
                d => {
                d.Range.Should().HaveRange((1, 23), (1, 24));
                d.Should().HaveCodeAndSeverity("BCP027", DiagnosticSeverity.Error);
            },
                d => {
                d.Range.Should().HaveRange((2, 15), (2, 30));
                d.Should().HaveCodeAndSeverity("BCP029", DiagnosticSeverity.Error);
            },
                d => {
                d.Range.Should().HaveRange((5, 0), (5, 11));
                d.Should().HaveCodeAndSeverity("BCP007", DiagnosticSeverity.Error);
            }
                );

            // change document
            diagsReceived = new TaskCompletionSource <PublishDiagnosticsParams>();
            client.TextDocument.DidChangeTextDocument(TextDocumentParamHelper.CreateDidChangeTextDocumentParams(documentUri, @"
param myParam string = 'fixed!'
resource myRes 'invalidFormat' = {

}
randomToken
", 2));

            response = await IntegrationTestHelper.WithTimeoutAsync(diagsReceived.Task);

            response.Diagnostics.Should().SatisfyRespectively(
                d => {
                d.Range.Should().HaveRange((2, 15), (2, 30));
                d.Should().HaveCodeAndSeverity("BCP029", DiagnosticSeverity.Error);
            },
                d => {
                d.Range.Should().HaveRange((5, 0), (5, 11));
                d.Should().HaveCodeAndSeverity("BCP007", DiagnosticSeverity.Error);
            }
                );

            // close document
            diagsReceived = new TaskCompletionSource <PublishDiagnosticsParams>();
            client.TextDocument.DidCloseTextDocument(TextDocumentParamHelper.CreateDidCloseTextDocumentParams(documentUri, 3));

            response = await IntegrationTestHelper.WithTimeoutAsync(diagsReceived.Task);

            response.Diagnostics.Should().BeEmpty();
        }
        public async Task RequestDocumentSymbol_should_return_full_symbol_list()
        {
            var documentUri   = DocumentUri.From("/template.bicep");
            var diagsReceived = new TaskCompletionSource <PublishDiagnosticsParams>();

            using var helper = await LanguageServerHelper.StartServerWithClientConnectionAsync(this.TestContext, options =>
            {
                options.OnPublishDiagnostics(diags =>
                {
                    diagsReceived.SetResult(diags);
                });
            });

            var client = helper.Client;

            // client opens the document
            client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(documentUri, @"
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
  name: 'test'
}
module myMod './module.bicep' = {
  name: 'test' 
}
output myOutput string = 'myOutput'
", 0));

            // client requests symbols
            var symbols = await client.TextDocument.RequestDocumentSymbol(new DocumentSymbolParams
            {
                TextDocument = new TextDocumentIdentifier
                {
                    Uri = documentUri,
                },
            });

            symbols.Should().SatisfyRespectively(
                x =>
            {
                x.DocumentSymbol !.Name.Should().Be("myParam");
                x.DocumentSymbol.Kind.Should().Be(SymbolKind.Field);
            },
                x =>
            {
                x.DocumentSymbol !.Name.Should().Be("myRes");
                x.DocumentSymbol.Kind.Should().Be(SymbolKind.Object);
            },
                x =>
            {
                x.DocumentSymbol !.Name.Should().Be("myMod");
                x.DocumentSymbol.Kind.Should().Be(SymbolKind.Module);
            },
                x =>
            {
                x.DocumentSymbol !.Name.Should().Be("myOutput");
                x.DocumentSymbol.Kind.Should().Be(SymbolKind.Interface);
            }
                );

            // client deletes the output and renames the resource
            client.TextDocument.DidChangeTextDocument(TextDocumentParamHelper.CreateDidChangeTextDocumentParams(documentUri, @"
param myParam string = 'test'
resource myRenamedRes 'myRp/provider@2019-01-01' = {
  name: 'test'
}
module myMod './module.bicep' = {
  name: 'test'
}
", 1));

            // client requests symbols
            symbols = await client.TextDocument.RequestDocumentSymbol(new DocumentSymbolParams
            {
                TextDocument = new TextDocumentIdentifier
                {
                    Uri = documentUri,
                },
            });

            symbols.Should().SatisfyRespectively(
                x =>
            {
                x.DocumentSymbol !.Name.Should().Be("myParam");
                x.DocumentSymbol.Kind.Should().Be(SymbolKind.Field);
            },
                x =>
            {
                x.DocumentSymbol !.Name.Should().Be("myRenamedRes");
                x.DocumentSymbol.Kind.Should().Be(SymbolKind.Object);
            },
                x =>
            {
                x.DocumentSymbol !.Name.Should().Be("myMod");
                x.DocumentSymbol.Kind.Should().Be(SymbolKind.Module);
            }
                );
        }
        public async Task DidOpenTextDocument_should_trigger_PublishDiagnostics()
        {
            var documentUri   = DocumentUri.From("/template.bicep");
            var diagsReceived = new TaskCompletionSource <PublishDiagnosticsParams>();

            var client = await IntegrationTestHelper.StartServerWithClientConnectionAsync(this.TestContext, options =>
            {
                options.OnPublishDiagnostics(diags => {
                    diagsReceived.SetResult(diags);
                });
            });

            // open document
            client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(documentUri, @"
param myParam string = 2
resource myRes 'invalidFormat' = {

}
randomToken
", 1));

            var response = await IntegrationTestHelper.WithTimeoutAsync(diagsReceived.Task);

            response.Diagnostics.Should().SatisfyRespectively(
                d => {
                d.Range.Should().HaveRange((1, 6), (1, 13));
                // note documentation pretty printing moves Uri to code for output
                d.Should().HaveCodeAndSeverity(new NoUnusedParametersRule().Uri !.AbsoluteUri, DiagnosticSeverity.Warning);
            },
                d => {
                d.Range.Should().HaveRange((1, 23), (1, 24));
                d.Should().HaveCodeAndSeverity("BCP027", DiagnosticSeverity.Error);
            },
                d => {
                d.Range.Should().HaveRange((2, 15), (2, 30));
                d.Should().HaveCodeAndSeverity("BCP029", DiagnosticSeverity.Error);
            },
                d => {
                d.Range.Should().HaveRange((5, 0), (5, 11));
                d.Should().HaveCodeAndSeverity("BCP007", DiagnosticSeverity.Error);
            }
                );

            // change document
            diagsReceived = new TaskCompletionSource <PublishDiagnosticsParams>();
            client.TextDocument.DidChangeTextDocument(TextDocumentParamHelper.CreateDidChangeTextDocumentParams(documentUri, @"
param myParam string = 'fixed!'
resource myRes 'invalidFormat' = {

}
randomToken
", 2));

            response = await IntegrationTestHelper.WithTimeoutAsync(diagsReceived.Task);

            response.Diagnostics.Should().SatisfyRespectively(
                d => {
                d.Range.Should().HaveRange((1, 6), (1, 13));
                // documentation provided with linter sets code to uri for pretty link print outs
                d.Should().HaveCodeAndSeverity(new NoUnusedParametersRule().Uri !.AbsoluteUri, DiagnosticSeverity.Warning);
            },
                d => {
                d.Range.Should().HaveRange((2, 15), (2, 30));
                d.Should().HaveCodeAndSeverity("BCP029", DiagnosticSeverity.Error);
            },
                d => {
                d.Range.Should().HaveRange((5, 0), (5, 11));
                d.Should().HaveCodeAndSeverity("BCP007", DiagnosticSeverity.Error);
            }
                );

            // close document
            diagsReceived = new TaskCompletionSource <PublishDiagnosticsParams>();
            client.TextDocument.DidCloseTextDocument(TextDocumentParamHelper.CreateDidCloseTextDocumentParams(documentUri, 3));

            response = await IntegrationTestHelper.WithTimeoutAsync(diagsReceived.Task);

            response.Diagnostics.Should().BeEmpty();
        }