diff --git a/src/BannedSymbols.txt b/src/BannedSymbols.txt index e7c6a22508b..6229037d299 100644 --- a/src/BannedSymbols.txt +++ b/src/BannedSymbols.txt @@ -37,3 +37,5 @@ M:System.Console.WriteLine(System.Decimal);Don't use Console.WriteLine for loggi M:Moq.Mock`1.#ctor();Don't use the default Mock constructor. Set Strict mode explicitly or use a MockRepository set to strict mode. M:Moq.Mock`1.#ctor(System.Object[]);Don't use the default Mock constructor. Set Strict mode explicitly or use a MockRepository set to strict mode. + +M:OmniSharp.Extensions.LanguageServer.Protocol.DocumentUri.ToUri();Use DocumentUri.ToUriEncoded() instead. diff --git a/src/Bicep.Core.IntegrationTests/Semantics/SemanticModelTests.cs b/src/Bicep.Core.IntegrationTests/Semantics/SemanticModelTests.cs index 68b7a2d24f6..df834dc09d9 100644 --- a/src/Bicep.Core.IntegrationTests/Semantics/SemanticModelTests.cs +++ b/src/Bicep.Core.IntegrationTests/Semantics/SemanticModelTests.cs @@ -197,7 +197,7 @@ public void GetAllDiagnostics_VerifyDisableNextLineDiagnosticsDirectiveDoesNotSu resource test"; var bicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", bicepFileContents); var documentUri = DocumentUri.FromFileSystemPath(bicepFilePath); - var uri = documentUri.ToUri(); + var uri = documentUri.ToUriEncoded(); var files = new Dictionary { @@ -243,7 +243,7 @@ public void GetAllDiagnostics_VerifyDisableNextLineDiagnosticsDirectiveSupportsC }"; var bicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", bicepFileContents); var documentUri = DocumentUri.FromFileSystemPath(bicepFilePath); - var uri = documentUri.ToUri(); + var uri = documentUri.ToUriEncoded(); var files = new Dictionary { @@ -262,7 +262,7 @@ public void GetAllDiagnostics_VerifyDisableNextLineDiagnosticsDirectiveSupportsL param storageAccount string = 'testStorageAccount'"; var bicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", bicepFileContents); var documentUri = DocumentUri.FromFileSystemPath(bicepFilePath); - var uri = documentUri.ToUri(); + var uri = documentUri.ToUriEncoded(); var files = new Dictionary { @@ -282,7 +282,7 @@ public void GetAllDiagnostics_WithNoDisableNextLineDiagnosticsDirectiveInPreviou param storageAccount string = 'testStorageAccount'"; var bicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", bicepFileContents); var documentUri = DocumentUri.FromFileSystemPath(bicepFilePath); - var uri = documentUri.ToUri(); + var uri = documentUri.ToUriEncoded(); var files = new Dictionary { diff --git a/src/Bicep.Core.UnitTests/Registry/OciModuleRegistryTests.cs b/src/Bicep.Core.UnitTests/Registry/OciModuleRegistryTests.cs index 805942ca308..22841742175 100644 --- a/src/Bicep.Core.UnitTests/Registry/OciModuleRegistryTests.cs +++ b/src/Bicep.Core.UnitTests/Registry/OciModuleRegistryTests.cs @@ -519,7 +519,7 @@ public async Task GetDescription_WithValidDescriptionAndDocumentationUriInManife { string testOutputPath = FileHelper.GetUniqueTestOutputPath(TestContext); var bicepPath = FileHelper.SaveResultFile(TestContext, "input.bicep", bicepFileContents, testOutputPath); - var parentModuleUri = DocumentUri.FromFileSystemPath(bicepPath).ToUri(); + var parentModuleUri = DocumentUri.FromFileSystemPath(bicepPath).ToUriEncoded(); var ociArtifactModuleReference = OciArtifactModuleReferenceHelper.GetModuleReferenceAndSaveManifestFile( TestContext, diff --git a/src/Bicep.LangServer.IntegrationTests/BicepConfigTests.cs b/src/Bicep.LangServer.IntegrationTests/BicepConfigTests.cs index 244b2e16b9e..ed788e02f2a 100644 --- a/src/Bicep.LangServer.IntegrationTests/BicepConfigTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/BicepConfigTests.cs @@ -495,7 +495,7 @@ public async Task WithMultipleConfigFiles_ShouldUseConfigSettingsFromRelevantDir string bicepFileContents = @"param storageAccountName string = 'test'"; var documentUriOfFileInChildDirectory = SaveFile("main.bicep", bicepFileContents, childDirectoryPath); - var uriOfFileInChildDirectory = documentUriOfFileInChildDirectory.ToUri(); + var uriOfFileInChildDirectory = documentUriOfFileInChildDirectory.ToUriEncoded(); // open the main document and verify diagnostics { @@ -511,7 +511,7 @@ await VerifyDiagnosticsAsync(diagsListener, uriOfFileInChildDirectory, (@"Parame // add bicepconfig.json to parent directory and verify diagnostics { var documentUriOfFileInParentDirectory = SaveFile("main.bicep", bicepFileContents, parentDirectoryPath); - var uriOfFileInParentDirectory = documentUriOfFileInParentDirectory.ToUri(); + var uriOfFileInParentDirectory = documentUriOfFileInParentDirectory.ToUriEncoded(); bicepConfigFileContents = @"{ ""analyzers"": { diff --git a/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs b/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs index 728512626de..7182f058363 100644 --- a/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs @@ -230,14 +230,14 @@ private async Task VerifyCodeActionIsAvailableToSuppressLinterDiagnostics(string var bicepFileContents = @"param storageAccount string = 'testStorageAccount'"; var bicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", bicepFileContents, testOutputPath); var documentUri = DocumentUri.FromFileSystemPath(bicepFilePath); - var uri = documentUri.ToUri(); + var uri = documentUri.ToUriEncoded(); var fileSystemDict = new Dictionary(); fileSystemDict[uri] = bicepFileContents; string bicepConfigFilePath = FileHelper.SaveResultFile(TestContext, "bicepconfig.json", bicepConfigFileContents, testOutputPath); var bicepConfigUri = DocumentUri.FromFileSystemPath(bicepConfigFilePath); - fileSystemDict[bicepConfigUri.ToUri()] = bicepConfigFileContents; + fileSystemDict[bicepConfigUri.ToUriEncoded()] = bicepConfigFileContents; var compilation = Services.BuildCompilation(fileSystemDict, uri); var diagnostics = compilation.GetEntrypointSemanticModel().GetAllDiagnostics(); @@ -271,7 +271,7 @@ public async Task VerifyCodeActionIsNotAvailableToSuppressCoreCompilerError() resource test"; var bicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", bicepFileContents); var documentUri = DocumentUri.FromFileSystemPath(bicepFilePath); - var uri = documentUri.ToUri(); + var uri = documentUri.ToUriEncoded(); var files = new Dictionary { @@ -333,7 +333,7 @@ public async Task VerifyCodeActionIsAvailableToSuppressCoreCompilerWarning() }"; var bicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", bicepFileContents); var documentUri = DocumentUri.FromFileSystemPath(bicepFilePath); - var uri = documentUri.ToUri(); + var uri = documentUri.ToUriEncoded(); var files = new Dictionary { diff --git a/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs b/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs index 060e3d0ae87..d8da5463768 100644 --- a/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs @@ -219,7 +219,7 @@ public async Task ValidateSnippetCompletionAfterPlaceholderReplacements(Completi private async Task RequestSnippetCompletion(string bicepFileName, CompletionData completionData, string placeholderFile, int cursor) { var documentUri = DocumentUri.FromFileSystemPath(bicepFileName); - var bicepFile = SourceFileFactory.CreateBicepFile(documentUri.ToUri(), placeholderFile); + var bicepFile = SourceFileFactory.CreateBicepFile(documentUri.ToUriEncoded(), placeholderFile); var helper = await ServerWithNamespaceProvider.GetAsync(); await helper.OpenFileOnceAsync(this.TestContext, placeholderFile, documentUri); @@ -3850,7 +3850,7 @@ public async Task ModuleRegistryReferenceCompletions_GetCompletionsAfterBrSchema .AddSingleton(settingsProvider.Object) .WithFileResolver(new FileResolver(new IOFileSystem()))); - var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUri(), text); + var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUriEncoded(), text); var completions = await file.RequestCompletion(cursor); completions.Count().Should().Be(3); @@ -3879,7 +3879,7 @@ public async Task ModuleRegistryReferenceCompletions_GetCompletionsForFolderInsi .AddSingleton(settingsProvider.Object) .WithFileResolver(new FileResolver(new IOFileSystem()))); - var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUri(), text); + var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUriEncoded(), text); var completions = await file.RequestCompletion(cursor); completions.Count().Should().Be(2); @@ -3915,7 +3915,7 @@ public async Task ModuleRegistryReferenceCompletions_GetPathCompletions(string i .AddSingleton(settingsProvider.Object) .WithFileResolver(new FileResolver(new IOFileSystem()))); - var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUri(), text); + var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUriEncoded(), text); var completions = await file.RequestCompletion(cursor); completions.Count().Should().Be(2); @@ -3949,7 +3949,7 @@ public async Task ModuleRegistryReferenceCompletions_GetVersionCompletions(strin .AddSingleton(settingsProvider.Object) .WithFileResolver(new FileResolver(new IOFileSystem()))); - var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUri(), text); + var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUriEncoded(), text); var completions = await file.RequestCompletion(cursor); completions.Count().Should().Be(2); diff --git a/src/Bicep.LangServer.IntegrationTests/DeploymentGraphTests.cs b/src/Bicep.LangServer.IntegrationTests/DeploymentGraphTests.cs index 036965f2391..bc2330e3e15 100644 --- a/src/Bicep.LangServer.IntegrationTests/DeploymentGraphTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/DeploymentGraphTests.cs @@ -34,7 +34,7 @@ public async Task RequestDeploymentGraphShouldReturnDeploymentGraph() var fileSystemDict = new Dictionary(); var mainUri = DocumentUri.FromFileSystemPath("/main.bicep"); - fileSystemDict[mainUri.ToUri()] = @" + fileSystemDict[mainUri.ToUriEncoded()] = @" resource res1 'Test.Rp/basicTests@2020-01-01' = { name: 'res1' } @@ -62,7 +62,7 @@ public async Task RequestDeploymentGraphShouldReturnDeploymentGraph() "; var module1Uri = DocumentUri.FromFileSystemPath("/modules/module1.bicep"); - fileSystemDict[module1Uri.ToUri()] = @" + fileSystemDict[module1Uri.ToUriEncoded()] = @" resource res3 'Test.Rp/basicTests@2020-01-01' = { name: 'res3' } @@ -71,7 +71,7 @@ public async Task RequestDeploymentGraphShouldReturnDeploymentGraph() "; var module2Uri = DocumentUri.FromFileSystemPath("/modules/module2.bicep"); - fileSystemDict[module2Uri.ToUri()] = @" + fileSystemDict[module2Uri.ToUriEncoded()] = @" resource res4 'Test.Rp/basicTests@2020-01-01' = { name: 'res4' } @@ -85,7 +85,7 @@ public async Task RequestDeploymentGraphShouldReturnDeploymentGraph() "; var nestedModuleUri = DocumentUri.FromFileSystemPath("/modules/nestedModules/nestedModule.bicep"); - fileSystemDict[nestedModuleUri.ToUri()] = @" + fileSystemDict[nestedModuleUri.ToUriEncoded()] = @" resource res5 'Test.Rp/basicTests@2020-01-01' = { name: 'res5' } @@ -97,7 +97,7 @@ public async Task RequestDeploymentGraphShouldReturnDeploymentGraph() services => services.WithNamespaceProvider(BuiltInTestTypes.Create()).WithFileResolver(new InMemoryFileResolver(fileSystemDict))); var client = helper.Client; - client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUri()], 1)); + client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUriEncoded()], 1)); await diagnosticsListener.WaitNext(); var deploymentGraph = await client.SendRequest(new BicepDeploymentGraphParams(new TextDocumentIdentifier(mainUri)), default); diff --git a/src/Bicep.LangServer.IntegrationTests/FileWatcherTests.cs b/src/Bicep.LangServer.IntegrationTests/FileWatcherTests.cs index 11ebadeed84..1e9ce964672 100644 --- a/src/Bicep.LangServer.IntegrationTests/FileWatcherTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/FileWatcherTests.cs @@ -51,7 +51,7 @@ public async Task Module_file_change_should_trigger_a_recompilation() var diagsListener = new MultipleMessageListener(); var mainUri = DocumentUri.FromFileSystemPath("/path/to/main.bicep"); - fileSystemDict[mainUri.ToUri()] = @" + fileSystemDict[mainUri.ToUriEncoded()] = @" module myMod '../toOther/module.bicep' = { name: 'myMod' params: { @@ -61,7 +61,7 @@ public async Task Module_file_change_should_trigger_a_recompilation() "; var moduleUri = DocumentUri.FromFileSystemPath("/path/toOther/module.bicep"); - fileSystemDict[moduleUri.ToUri()] = @" + fileSystemDict[moduleUri.ToUriEncoded()] = @" // mis-spelling! param requiredIpnut string "; @@ -73,7 +73,7 @@ param requiredIpnut string // open the main document { - client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUri()], 1)); + client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUriEncoded()], 1)); var diagsParams = await diagsListener.WaitNext(); diagsParams.Uri.Should().Be(mainUri); @@ -82,7 +82,7 @@ param requiredIpnut string // open the module document. this should trigger diagnostics for both the module and the main doc which references it. { - client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(moduleUri, fileSystemDict[moduleUri.ToUri()], 1)); + client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(moduleUri, fileSystemDict[moduleUri.ToUriEncoded()], 1)); var diagsParams = await diagsListener.WaitNext(); diagsParams.Uri.Should().Be(moduleUri); @@ -129,7 +129,7 @@ public async Task Background_file_deletion_should_trigger_a_recompilation() var diagsListener = new MultipleMessageListener(); var mainUri = DocumentUri.FromFileSystemPath("/path/to/main.bicep"); - fileSystemDict[mainUri.ToUri()] = @" + fileSystemDict[mainUri.ToUriEncoded()] = @" module myMod '../toOther/module.bicep' = { name: 'myMod' params: { @@ -139,7 +139,7 @@ public async Task Background_file_deletion_should_trigger_a_recompilation() "; var moduleUri = DocumentUri.FromFileSystemPath("/path/toOther/module.bicep"); - fileSystemDict[moduleUri.ToUri()] = @" + fileSystemDict[moduleUri.ToUriEncoded()] = @" // mis-spelling! param requiredIpnut string "; @@ -153,7 +153,7 @@ param requiredIpnut string // open the main document { - client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUri()], 1)); + client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUriEncoded()], 1)); var diagsParams = await diagsListener.WaitNext(); diagsParams.Uri.Should().Be(mainUri); @@ -196,7 +196,7 @@ public async Task Background_folder_deletion_should_trigger_a_recompilation() var diagsListener = new MultipleMessageListener(); var mainUri = DocumentUri.FromFileSystemPath("/path/to/main.bicep"); - fileSystemDict[mainUri.ToUri()] = @" + fileSystemDict[mainUri.ToUriEncoded()] = @" module myMod '../toOther/module.bicep' = { name: 'myMod' params: { @@ -206,7 +206,7 @@ public async Task Background_folder_deletion_should_trigger_a_recompilation() "; var moduleUri = DocumentUri.FromFileSystemPath("/path/toOther/module.bicep"); - fileSystemDict[moduleUri.ToUri()] = @" + fileSystemDict[moduleUri.ToUriEncoded()] = @" // mis-spelling! param requiredIpnut string "; @@ -220,7 +220,7 @@ param requiredIpnut string // open the main document { - client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUri()], 1)); + client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUriEncoded()], 1)); var diagsParams = await diagsListener.WaitNext(); diagsParams.Uri.Should().Be(mainUri); diff --git a/src/Bicep.LangServer.IntegrationTests/Helpers/LanguageServerHelper.cs b/src/Bicep.LangServer.IntegrationTests/Helpers/LanguageServerHelper.cs index d87437232bb..500d84f5712 100644 --- a/src/Bicep.LangServer.IntegrationTests/Helpers/LanguageServerHelper.cs +++ b/src/Bicep.LangServer.IntegrationTests/Helpers/LanguageServerHelper.cs @@ -73,7 +73,7 @@ public static async Task StartServer(TestContext testConte /// No further file opening is possible. /// public static Task StartServerWithText(TestContext testContext, string text, DocumentUri documentUri, Action? onRegisterServices = null) - => StartServerWithText(testContext, new Dictionary { [documentUri.ToUri()] = text }, documentUri.ToUri(), onRegisterServices); + => StartServerWithText(testContext, new Dictionary { [documentUri.ToUriEncoded()] = text }, documentUri.ToUriEncoded(), onRegisterServices); /// /// Starts a language client/server pair that will load the specified Bicep text and wait for the diagnostics to be published. diff --git a/src/Bicep.LangServer.IntegrationTests/Helpers/TextDocumentParamHelper.cs b/src/Bicep.LangServer.IntegrationTests/Helpers/TextDocumentParamHelper.cs index a7ea6ca258b..7026572971e 100644 --- a/src/Bicep.LangServer.IntegrationTests/Helpers/TextDocumentParamHelper.cs +++ b/src/Bicep.LangServer.IntegrationTests/Helpers/TextDocumentParamHelper.cs @@ -16,8 +16,8 @@ public static DidOpenTextDocumentParams CreateDidOpenDocumentParams(DocumentUri TextDocument = new TextDocumentItem { LanguageId = - PathHelper.HasBicepparamsExension(documentUri.ToUri()) ? LanguageConstants.ParamsLanguageId : - PathHelper.HasArmTemplateLikeExtension(documentUri.ToUri()) ? LanguageConstants.ArmTemplateLanguageId : + PathHelper.HasBicepparamsExension(documentUri.ToUriEncoded()) ? LanguageConstants.ParamsLanguageId : + PathHelper.HasArmTemplateLikeExtension(documentUri.ToUriEncoded()) ? LanguageConstants.ArmTemplateLanguageId : LanguageConstants.LanguageId, Version = version, Uri = documentUri, diff --git a/src/Bicep.LangServer.IntegrationTests/HoverTests.cs b/src/Bicep.LangServer.IntegrationTests/HoverTests.cs index 31c7546aa65..5bc64706a33 100644 --- a/src/Bicep.LangServer.IntegrationTests/HoverTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/HoverTests.cs @@ -817,7 +817,7 @@ public async Task Verify_Hover_ContainerRegistry(string? documentationUri, strin string testOutputPath = FileHelper.GetUniqueTestOutputPath(TestContext); var bicepPath = FileHelper.SaveResultFile(TestContext, "input.bicep", bicepFileContents, testOutputPath); var documentUri = DocumentUri.FromFileSystemPath(bicepPath); - var parentModuleUri = documentUri.ToUri(); + var parentModuleUri = documentUri.ToUriEncoded(); var client = await GetLanguageClientAsync( documentUri, diff --git a/src/Bicep.LangServer.IntegrationTests/SemanticTokenTests.cs b/src/Bicep.LangServer.IntegrationTests/SemanticTokenTests.cs index 69c555495ea..046d0800ba9 100644 --- a/src/Bicep.LangServer.IntegrationTests/SemanticTokenTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/SemanticTokenTests.cs @@ -54,7 +54,7 @@ public static async Task ClassCleanup() public async Task Overlapping_tokens_are_not_returned(DataSet dataSet) { var uri = DocumentUri.From($"/{dataSet.Name}"); - var bicepFile = SourceFileFactory.CreateBicepFile(uri.ToUri(), dataSet.Bicep); + var bicepFile = SourceFileFactory.CreateBicepFile(uri.ToUriEncoded(), dataSet.Bicep); var helper = await DefaultServer.GetAsync(); await helper.OpenFileOnceAsync(TestContext, dataSet.Bicep, uri); diff --git a/src/Bicep.LangServer.IntegrationTests/TelemetryTests.cs b/src/Bicep.LangServer.IntegrationTests/TelemetryTests.cs index 135baf73445..437680f1188 100644 --- a/src/Bicep.LangServer.IntegrationTests/TelemetryTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/TelemetryTests.cs @@ -157,7 +157,7 @@ public async Task VerifyDisableNextLineCodeActionInvocationFiresTelemetryEvent() var bicepFileContents = @"param storageAccount string = 'testStorageAccount'"; var bicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", bicepFileContents); var documentUri = DocumentUri.FromFileSystemPath(bicepFilePath); - var uri = documentUri.ToUri(); + var uri = documentUri.ToUriEncoded(); var files = new Dictionary { @@ -517,11 +517,11 @@ private async Task VerifyBicepFileOpenTelemetry( var mainBicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", mainBicepFileContents, testOutputPath); var mainUri = DocumentUri.FromFileSystemPath(mainBicepFilePath); - fileSystemDict[mainUri.ToUri()] = mainBicepFileContents; + fileSystemDict[mainUri.ToUriEncoded()] = mainBicepFileContents; var referencedBicepFilePath = FileHelper.SaveResultFile(TestContext, "groups.bicep", referencedBicepFileContents, testOutputPath); var moduleUri = DocumentUri.FromFileSystemPath(referencedBicepFilePath); - fileSystemDict[moduleUri.ToUri()] = referencedBicepFileContents; + fileSystemDict[moduleUri.ToUriEncoded()] = referencedBicepFileContents; var telemetryEventsListener = new MultipleMessageListener(); @@ -531,7 +531,7 @@ private async Task VerifyBicepFileOpenTelemetry( services => services.WithFileResolver(new InMemoryFileResolver(fileSystemDict))); var client = helper.Client; - client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUri()], 1)); + client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUriEncoded()], 1)); var bicepTelemetryEvent = await telemetryEventsListener.WaitNext(); @@ -558,9 +558,9 @@ private async Task ResolveCompletionAsync(string text, stri var client = helper.Client; var mainUri = DocumentUri.FromFileSystemPath("/main.bicep"); - fileSystemDict[mainUri.ToUri()] = text; + fileSystemDict[mainUri.ToUriEncoded()] = text; - client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUri()], 1)); + client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(mainUri, fileSystemDict[mainUri.ToUriEncoded()], 1)); var bicepTelemetryEvent = await telemetryEventsListener.WaitNext(); bicepTelemetryEvent.EventName.Should().Be(TelemetryConstants.EventNames.LinterRuleStateOnBicepFileOpen); diff --git a/src/Bicep.LangServer.IntegrationTests/TextDocumentSyncTests.cs b/src/Bicep.LangServer.IntegrationTests/TextDocumentSyncTests.cs index 34afc14bdd2..54c84d5b8c4 100644 --- a/src/Bicep.LangServer.IntegrationTests/TextDocumentSyncTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/TextDocumentSyncTests.cs @@ -106,9 +106,8 @@ public async Task DidOpenTextDocument_should_trigger_PublishDiagnostics() } [TestMethod] - public async Task Module_resolution_does_not_work_for_file_paths_containing_escaped_spaces() + public async Task Module_resolution_works_for_file_paths_containing_escaped_spaces() { - // Here's a repro for https://github.com/Azure/bicep/issues/9466. It has not yet been fixed, but this test makes it simple to debug. var diagsListener = new MultipleMessageListener(); var entryPointUri = new Uri("file:///src/demo%2520repo/main.bicep"); var fileSystemDict = new Dictionary @@ -132,7 +131,7 @@ [new Uri("file:///src/demo%2520repo/storage-account.bicep")] = @" client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(entryPointUri, fileSystemDict[entryPointUri], 1)); var diagnostics = await diagsListener.WaitNext(); - diagnostics.Diagnostics.Should().Contain(x => x.Code == "BCP091" && x.Message == "An error occurred reading file. Could not find file '/src/demo repo/storage-account.bicep'."); + diagnostics.Diagnostics.Should().BeEmpty(); } } } diff --git a/src/Bicep.LangServer.UnitTests/BicepCompilationManagerTests.cs b/src/Bicep.LangServer.UnitTests/BicepCompilationManagerTests.cs index af09fa1d8be..e190907f35d 100644 --- a/src/Bicep.LangServer.UnitTests/BicepCompilationManagerTests.cs +++ b/src/Bicep.LangServer.UnitTests/BicepCompilationManagerTests.cs @@ -65,7 +65,7 @@ public void UpsertCompilation_NotInWorspaceArmTemplateFile_ShouldNotUpsert(strin var document = BicepCompilationManagerHelper.CreateMockDocument(p => receivedParams = p); var server = BicepCompilationManagerHelper.CreateMockServer(document); - var uri = DocumentUri.File(this.TestContext.TestName + fileExtension).ToUri(); + var uri = DocumentUri.File(this.TestContext.TestName + fileExtension).ToUriEncoded(); var workspace = new Workspace(); var manager = BicepCompilationManagerHelper.CreateCompilationManager(uri, string.Empty); @@ -95,7 +95,7 @@ public void UpsertCompilation_InWorspaceArmTemplateFile_ShouldRefreshWorkspace(s PublishDiagnosticsParams? receivedParams = null; var document = BicepCompilationManagerHelper.CreateMockDocument(p => receivedParams = p); - var uri = DocumentUri.File(this.TestContext.TestName + fileExtension).ToUri(); + var uri = DocumentUri.File(this.TestContext.TestName + fileExtension).ToUriEncoded(); var originalFile = SourceFileFactory.CreateArmTemplateFile(uri, "{}"); var workspace = new Workspace(); @@ -558,7 +558,7 @@ void EnsureSemanticModelsAndSourceFilesDeduplicated() compilationManager.OpenCompilation(uris.main, 1, fileDict[uris.main], "bicep"); diagsReceieved.Should().SatisfyRespectively( - x => x.Uri.ToUri().Should().Be(uris.main) + x => x.Uri.ToUriEncoded().Should().Be(uris.main) ); diagsReceieved.Clear(); } @@ -578,8 +578,8 @@ void EnsureSemanticModelsAndSourceFilesDeduplicated() compilationManager.OpenCompilation(uris.moduleA, 2, fileDict[uris.moduleA], "bicep"); diagsReceieved.Should().SatisfyRespectively( - x => x.Uri.ToUri().Should().Be(uris.moduleA), - x => x.Uri.ToUri().Should().Be(uris.main) + x => x.Uri.ToUriEncoded().Should().Be(uris.moduleA), + x => x.Uri.ToUriEncoded().Should().Be(uris.main) ); diagsReceieved.Clear(); @@ -598,8 +598,8 @@ void EnsureSemanticModelsAndSourceFilesDeduplicated() compilationManager.OpenCompilation(uris.moduleC, 2, fileDict[uris.moduleC], "bicep"); diagsReceieved.Should().SatisfyRespectively( - x => x.Uri.ToUri().Should().Be(uris.moduleC), - x => x.Uri.ToUri().Should().Be(uris.main) + x => x.Uri.ToUriEncoded().Should().Be(uris.moduleC), + x => x.Uri.ToUriEncoded().Should().Be(uris.main) ); diagsReceieved.Clear(); @@ -611,7 +611,7 @@ void EnsureSemanticModelsAndSourceFilesDeduplicated() compilationManager.OpenCompilation(uris.main, 3, fileDict[uris.main], "bicep"); diagsReceieved.Should().SatisfyRespectively( - x => x.Uri.ToUri().Should().Be(uris.main) + x => x.Uri.ToUriEncoded().Should().Be(uris.main) ); diagsReceieved.Clear(); @@ -844,7 +844,7 @@ public void GetTelemetryAboutSourceFiles_ShouldReturnTelemetryEvent() param location string = 'testLocation'"; var testOutputPath = FileHelper.GetUniqueTestOutputPath(TestContext); var bicepFilePath = FileHelper.SaveResultFile(TestContext, "main.bicep", bicepFileContents, testOutputPath); - var mainUri = DocumentUri.FromFileSystemPath(bicepFilePath).ToUri(); + var mainUri = DocumentUri.FromFileSystemPath(bicepFilePath).ToUriEncoded(); var bicepFile = SourceFileFactory.CreateBicepFile(mainUri, bicepFileContents); @@ -884,7 +884,7 @@ private RootConfiguration GetRootConfiguration(string testOutputPath, string bic var bicepConfigFilePath = FileHelper.SaveResultFile(TestContext, "bicepconfig.json", bicepConfigContents, testOutputPath); var bicepConfigUri = DocumentUri.FromFileSystemPath(bicepConfigFilePath); - return configurationManager.GetConfiguration(bicepConfigUri.ToUri()); + return configurationManager.GetConfiguration(bicepConfigUri.ToUriEncoded()); } private BicepCompilationManager CreateBicepCompilationManager() diff --git a/src/Bicep.LangServer.UnitTests/BicepCompilationProviderTests.cs b/src/Bicep.LangServer.UnitTests/BicepCompilationProviderTests.cs index 14bbb98d104..65efd57b276 100644 --- a/src/Bicep.LangServer.UnitTests/BicepCompilationProviderTests.cs +++ b/src/Bicep.LangServer.UnitTests/BicepCompilationProviderTests.cs @@ -33,7 +33,7 @@ public void Create_ShouldReturnValidCompilation() var fileUri = DocumentUri.Parse($"/{DataSets.Parameters_LF.Name}.bicep"); var provider = Create(); - var sourceFile = SourceFileFactory.CreateSourceFile(fileUri.ToUri(), DataSets.Parameters_LF.Bicep); + var sourceFile = SourceFileFactory.CreateSourceFile(fileUri.ToUriEncoded(), DataSets.Parameters_LF.Bicep); var workspace = new Workspace(); workspace.UpsertSourceFile(sourceFile); diff --git a/src/Bicep.LangServer.UnitTests/Completions/ModuleReferenceCompletionProviderTests.cs b/src/Bicep.LangServer.UnitTests/Completions/ModuleReferenceCompletionProviderTests.cs index e14abd8ae44..98f2bccca42 100644 --- a/src/Bicep.LangServer.UnitTests/Completions/ModuleReferenceCompletionProviderTests.cs +++ b/src/Bicep.LangServer.UnitTests/Completions/ModuleReferenceCompletionProviderTests.cs @@ -54,7 +54,7 @@ public async Task GetFilteredCompletions_WithBicepRegistryAndTemplateSpecShemaCo publicRegistryModuleMetadataProvider, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Count().Should().Be(4); @@ -133,7 +133,7 @@ public async Task GetFilteredCompletions_WithBicepRegistryAndTemplateSpecShemaCo publicRegistryModuleMetadataProvider, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Count().Should().Be(5); @@ -200,7 +200,7 @@ public async Task GetFilteredCompletions_WithInvalidTextInCompletionContext_Retu publicRegistryModuleMetadataProvider, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().BeEmpty(); } @@ -222,7 +222,7 @@ public async Task GetFilteredCompletions_WithInvalidCompletionContext_ReturnsEmp publicRegistryModuleMetadataProvider.Object, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().BeEmpty(); } @@ -252,7 +252,7 @@ public async Task GetFilteredCompletions_WithAliasCompletionContext_ReturnsCompl publicRegistryModuleMetadataProvider, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().SatisfyRespectively( c => @@ -328,7 +328,7 @@ public async Task GetFilteredCompletions_WithACRCompletionSettingSetToFalse_Retu publicRegistryModuleMetadataProvider, settingsProviderMock.Object, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().SatisfyRespectively( c => @@ -393,7 +393,7 @@ public async Task GetFilteredCompletions_WithACRCompletionsSettingSetToTrue_Retu settingsProviderMock.Setup(x => x.GetSetting(LangServerConstants.GetAllAzureContainerRegistriesForCompletionsSetting)).Returns(true); var azureContainerRegistriesProvider = StrictMock.Of(); - azureContainerRegistriesProvider.Setup(x => x.GetRegistryUris(documentUri.ToUri(), CancellationToken.None)).Returns(new List { "testacr3.azurecr.io", "testacr4.azurecr.io" }.ToAsyncEnumerable()); + azureContainerRegistriesProvider.Setup(x => x.GetRegistryUris(documentUri.ToUriEncoded(), CancellationToken.None)).Returns(new List { "testacr3.azurecr.io", "testacr4.azurecr.io" }.ToAsyncEnumerable()); var moduleReferenceCompletionProvider = new ModuleReferenceCompletionProvider( azureContainerRegistriesProvider.Object, @@ -401,7 +401,7 @@ public async Task GetFilteredCompletions_WithACRCompletionsSettingSetToTrue_Retu publicRegistryModuleMetadataProvider, settingsProviderMock.Object, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().SatisfyRespectively( c => @@ -445,7 +445,7 @@ public async Task GetFilteredCompletions_WithACRCompletionsSettingSetToTrue_AndN settingsProviderMock.Setup(x => x.GetSetting(LangServerConstants.GetAllAzureContainerRegistriesForCompletionsSetting)).Returns(true); var azureContainerRegistriesProvider = StrictMock.Of(); - azureContainerRegistriesProvider.Setup(x => x.GetRegistryUris(documentUri.ToUri(), CancellationToken.None)).Returns(new List().ToAsyncEnumerable()); + azureContainerRegistriesProvider.Setup(x => x.GetRegistryUris(documentUri.ToUriEncoded(), CancellationToken.None)).Returns(new List().ToAsyncEnumerable()); var moduleReferenceCompletionProvider = new ModuleReferenceCompletionProvider( azureContainerRegistriesProvider.Object, @@ -453,7 +453,7 @@ public async Task GetFilteredCompletions_WithACRCompletionsSettingSetToTrue_AndN publicRegistryModuleMetadataProvider, settingsProviderMock.Object, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().SatisfyRespectively( c => @@ -490,7 +490,7 @@ public async Task GetFilteredCompletions_WithPublicMcrModuleRegistryCompletionCo publicRegistryModuleMetadataProvider.Object, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().SatisfyRespectively( c => @@ -555,7 +555,7 @@ public async Task GetFilteredCompletions_WithPathCompletionContext_ReturnsComple publicRegistryModuleMetadataProvider, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().Contain( x => x.Label == expectedLabel && @@ -608,7 +608,7 @@ public async Task GetFilteredCompletions_WithMcrVersionCompletionContext_Returns publicRegistryModuleMetadataProvider.Object, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().Contain(c => c.Label == expectedLabel1) .Which.Should().Match(x => @@ -650,7 +650,7 @@ public async Task GetFilteredCompletions_WithMcrVersionCompletionContext_AndNoMa publicRegistryModuleMetadataProvider.Object, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().BeEmpty(); } @@ -687,7 +687,7 @@ public async Task GetFilteredCompletions_WithPublicAliasOverriddenInBicepConfigA publicRegistryModuleMetadataProvider, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + var completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); completions.Should().Contain( x => x.Label == expectedLabel && @@ -737,7 +737,7 @@ public async Task GetFilteredCompletions_WithAliasForMCRInBicepConfigAndModulePa publicRegistryModuleMetadataProvider.Object, settingsProvider, BicepTestConstants.CreateMockTelemetryProvider().Object); - IEnumerable completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + IEnumerable completions = await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); CompletionItem actualCompletionItem = completions.First(x => x.Label == expectedLabel); actualCompletionItem.Kind.Should().Be(CompletionItemKind.Snippet); @@ -798,7 +798,7 @@ public async Task VerifyTelemetryEventIsPostedOnModuleRegistryPathCompletion(str publicRegistryModuleMetadataProvider.Object, settingsProvider, telemetryProvider.Object); - await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, CancellationToken.None); + await moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, CancellationToken.None); telemetryProvider.Verify(m => m.PostEvent(It.Is( p => p.EventName == TelemetryConstants.EventNames.ModuleRegistryPathCompletion && @@ -840,7 +840,7 @@ async IAsyncEnumerable GetUris([EnumeratorCancellation] CancellationToke secondItemReturned = true; yield return "testacr4.azurecr.io"; } - azureContainerRegistriesProvider.Setup(x => x.GetRegistryUris(documentUri.ToUri(), It.IsAny())) + azureContainerRegistriesProvider.Setup(x => x.GetRegistryUris(documentUri.ToUriEncoded(), It.IsAny())) .Returns((Uri uri, CancellationToken ct) => GetUris(ct)); var moduleReferenceCompletionProvider = new ModuleReferenceCompletionProvider( @@ -850,7 +850,7 @@ async IAsyncEnumerable GetUris([EnumeratorCancellation] CancellationToke settingsProviderMock.Object, BicepTestConstants.CreateMockTelemetryProvider().Object); - var func = () => moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUri(), completionContext, cts.Token); + var func = () => moduleReferenceCompletionProvider.GetFilteredCompletions(documentUri.ToUriEncoded(), completionContext, cts.Token); await func.Should().ThrowAsync(); firstItemReturned.Should().BeTrue(); diff --git a/src/Bicep.LangServer.UnitTests/Configuration/ConfigurationHelperTests.cs b/src/Bicep.LangServer.UnitTests/Configuration/ConfigurationHelperTests.cs index f5a9ae7139f..f94ee5cd24e 100644 --- a/src/Bicep.LangServer.UnitTests/Configuration/ConfigurationHelperTests.cs +++ b/src/Bicep.LangServer.UnitTests/Configuration/ConfigurationHelperTests.cs @@ -57,7 +57,7 @@ public void TryGetConfiguration_WithValidDocumentUri_ShoudReturnRootConfiguratio }"; var bicepConfigFilePath = FileHelper.SaveResultFile(TestContext, "bicepconfig.json", bicepConfigFileContents, testOutputPath); - var bicepConfigUri = DocumentUri.FromFileSystemPath(bicepConfigFilePath).ToUri(); + var bicepConfigUri = DocumentUri.FromFileSystemPath(bicepConfigFilePath).ToUriEncoded(); bool result = ConfigurationHelper.TryGetConfiguration(new ConfigurationManager(new IOFileSystem()), bicepConfigUri, out RootConfiguration? rootConfiguration); diff --git a/src/Bicep.LangServer.UnitTests/Handlers/BicepDecompileCommandHandlerTests.cs b/src/Bicep.LangServer.UnitTests/Handlers/BicepDecompileCommandHandlerTests.cs index 365bcb9be77..699c0d5b185 100644 --- a/src/Bicep.LangServer.UnitTests/Handlers/BicepDecompileCommandHandlerTests.cs +++ b/src/Bicep.LangServer.UnitTests/Handlers/BicepDecompileCommandHandlerTests.cs @@ -451,7 +451,7 @@ public async Task SimpleJson_OutputFileAlreadyExists_AndLotsOfExistingCopies_And var server = new LanguageServerMock(); string? displayedDoc = null; - server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUri().LocalPath); + server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUriEncoded().LocalPath); var (handler, saveHandler) = CreateHandlers(server); var result = await handler.Handle( @@ -481,7 +481,7 @@ public async Task MultiFileDecompilation_ShouldCreateMultipleOutputFiles() var server = new LanguageServerMock(); string? displayedDoc = null; - server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUri().LocalPath); + server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUriEncoded().LocalPath); var (handler, saveHandler) = CreateHandlers(server); var result = await handler.Handle( @@ -521,7 +521,7 @@ public async Task MultiFileDecompilation_MainFileConflicts_UserSelectsOverwriteA var server = new LanguageServerMock(); string? displayedDoc = null; - server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUri().LocalPath); + server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUriEncoded().LocalPath); var (handler, saveHandler) = CreateHandlers(server); var result = await handler.Handle( @@ -559,7 +559,7 @@ public async Task MultiFileDecompilation_OtherFilesConflict_UserSelectsOverwrite var server = new LanguageServerMock(); string? displayedDoc = null; - server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUri().LocalPath); + server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUriEncoded().LocalPath); var (handler, saveHandler) = CreateHandlers(server); var result = await handler.Handle( @@ -602,7 +602,7 @@ public async Task MultiFileDecompilation_OtherFilesConflict_UserSelectsCopy() var server = new LanguageServerMock(); string? displayedDoc = null; - server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUri().LocalPath); + server.WindowMock.OnShowDocument(p => displayedDoc = p.Uri.ToUriEncoded().LocalPath); var (handler, saveHandler) = CreateHandlers(server); var result = await handler.Handle( diff --git a/src/Bicep.LangServer.UnitTests/Telemetry/TelemetryHelperTests.cs b/src/Bicep.LangServer.UnitTests/Telemetry/TelemetryHelperTests.cs index dcda20b7bf8..ae3c6d9212c 100644 --- a/src/Bicep.LangServer.UnitTests/Telemetry/TelemetryHelperTests.cs +++ b/src/Bicep.LangServer.UnitTests/Telemetry/TelemetryHelperTests.cs @@ -531,7 +531,7 @@ private RootConfiguration GetRootConfiguration(string testOutputPath, string bic var bicepConfigFilePath = FileHelper.SaveResultFile(TestContext, "bicepconfig.json", bicepConfigContents, testOutputPath); var bicepConfigUri = DocumentUri.FromFileSystemPath(bicepConfigFilePath); - return configurationManager.GetConfiguration(bicepConfigUri.ToUri()); + return configurationManager.GetConfiguration(bicepConfigUri.ToUriEncoded()); } } } diff --git a/src/Bicep.LangServer/BicepCompilationManager.cs b/src/Bicep.LangServer/BicepCompilationManager.cs index f758859ac4e..8c738c632cb 100644 --- a/src/Bicep.LangServer/BicepCompilationManager.cs +++ b/src/Bicep.LangServer/BicepCompilationManager.cs @@ -73,7 +73,7 @@ public void RefreshCompilation(DocumentUri documentUri) // When errors are fixed in bicepconfig.json and file is saved, we'll get called into this // method again. CompilationContext will be null. We'll get the souceFile from workspace and // upsert compilation. - if (workspace.TryGetSourceFile(documentUri.ToUri(), out ISourceFile? sourceFile) && sourceFile is BicepFile) + if (workspace.TryGetSourceFile(documentUri.ToUriEncoded(), out ISourceFile? sourceFile) && sourceFile is BicepFile) { UpsertCompilationInternal(documentUri, null, sourceFile); } @@ -117,13 +117,13 @@ public void UpdateCompilation(DocumentUri documentUri, int? version, string file private ISourceFile CreateSourceFile(DocumentUri documentUri, string fileContents, string? languageId) { if (languageId is not null && - SourceFileFactory.TryCreateSourceFileByBicepLanguageId(documentUri.ToUri(), fileContents, languageId) is { } sourceFileViaLanguageId) + SourceFileFactory.TryCreateSourceFileByBicepLanguageId(documentUri.ToUriEncoded(), fileContents, languageId) is { } sourceFileViaLanguageId) { return sourceFileViaLanguageId; } // try creating the file using the URI (like in the SourceFileGroupingBuilder) - if (SourceFileFactory.TryCreateSourceFile(documentUri.ToUri(), fileContents) is { } sourceFileViaUri) + if (SourceFileFactory.TryCreateSourceFile(documentUri.ToUriEncoded(), fileContents) is { } sourceFileViaUri) { // this handles *.bicep, *.bicepparam, *.jsonc, *.json, and *.arm files return sourceFileViaUri; @@ -133,12 +133,12 @@ private ISourceFile CreateSourceFile(DocumentUri documentUri, string fileContent // this means we're dealing with an untitled file // however the language ID was made available to us on file open if (this.GetCompilationUnsafe(documentUri) is { } potentiallyUnsafeContext && - SourceFileFactory.TryCreateSourceFileByFileKind(documentUri.ToUri(), fileContents, potentiallyUnsafeContext.SourceFileKind) is { } sourceFileViaFileKind) + SourceFileFactory.TryCreateSourceFileByFileKind(documentUri.ToUriEncoded(), fileContents, potentiallyUnsafeContext.SourceFileKind) is { } sourceFileViaFileKind) { return sourceFileViaFileKind; } - throw new InvalidOperationException($"Unable to create source file for uri '{documentUri.ToUri()}'."); + throw new InvalidOperationException($"Unable to create source file for uri '{documentUri.ToUriEncoded()}'."); } private void UpsertCompilationInternal(DocumentUri documentUri, int? version, ISourceFile newFile, bool triggeredByFileOpenEvent = false) @@ -182,7 +182,7 @@ public void HandleFileChanges(IEnumerable fileEvents) } // We treat both updates and deletes as 'removes' to force the new SourceFile to be reloaded from disk - if (workspace.TryGetSourceFile(change.Uri.ToUri(), out var removedFile)) + if (workspace.TryGetSourceFile(change.Uri.ToUriEncoded(), out var removedFile)) { removedFiles.Add(removedFile); } @@ -190,7 +190,7 @@ public void HandleFileChanges(IEnumerable fileEvents) { // If we don't know definitively that we're deleting a file, we have to assume it's a directory; the file system watcher does not give us any information to differentiate reliably. // We could possibly assume that if the path ends in '.bicep', we've got a file, but this would discount directories ending in '.bicep', however unlikely. - var subdirRemovedFiles = workspace.GetSourceFilesForDirectory(change.Uri.ToUri()); + var subdirRemovedFiles = workspace.GetSourceFilesForDirectory(change.Uri.ToUriEncoded()); removedFiles.UnionWith(subdirRemovedFiles); } } @@ -225,7 +225,7 @@ private bool ShouldUpsertCompilation(DocumentUri documentUri, string? languageId // We should only upsert compilation when languageId is bicep or the file is already tracked in workspace. // When the file is in workspace but languageId is null, the file can be a bicep file or a JSON template // being referenced as a bicep module. - return LanguageConstants.IsBicepOrParamsLanguage(languageId) || this.workspace.TryGetSourceFile(documentUri.ToUri(), out var _); + return LanguageConstants.IsBicepOrParamsLanguage(languageId) || this.workspace.TryGetSourceFile(documentUri.ToUriEncoded(), out var _); } private ImmutableArray CloseCompilationInternal(DocumentUri documentUri, int? version, IEnumerable closingDiagnostics) @@ -258,7 +258,7 @@ private CompilationContextBase CreateCompilationContext(IWorkspace workspace, Do } catch (Exception exception) { - if (!workspace.TryGetSourceFile(documentUri.ToUri(), out var sourceFile)) + if (!workspace.TryGetSourceFile(documentUri.ToUriEncoded(), out var sourceFile)) { // the document is somehow missing from the workspace, // which should not happen since we upsert into the workspace before creating the compilation @@ -340,7 +340,7 @@ private CompilationContextBase CreateCompilationContext(IWorkspace workspace, Do if (triggeredByFileOpenEvent) { var model = context.Compilation.GetEntrypointSemanticModel(); - SendTelemetryOnBicepFileOpen(model, documentUri.ToUri(), model.Configuration, sourceFiles, diagnostics); + SendTelemetryOnBicepFileOpen(model, documentUri.ToUriEncoded(), model.Configuration, sourceFiles, diagnostics); } // publish all the diagnostics @@ -379,7 +379,7 @@ private void SendTelemetryOnBicepFileOpen(SemanticModel semanticModel, DocumentU TelemetryProvider.PostEvent(telemetryEvent); // Telemetry on open bicep file and the referenced modules - telemetryEvent = GetTelemetryAboutSourceFiles(semanticModel, documentUri.ToUri(), sourceFiles, diagnostics); + telemetryEvent = GetTelemetryAboutSourceFiles(semanticModel, documentUri.ToUriEncoded(), sourceFiles, diagnostics); if (telemetryEvent is not null) { diff --git a/src/Bicep.LangServer/Configuration/BicepConfigChangeHandler.cs b/src/Bicep.LangServer/Configuration/BicepConfigChangeHandler.cs index 62d5932ff5c..6427f2a815b 100644 --- a/src/Bicep.LangServer/Configuration/BicepConfigChangeHandler.cs +++ b/src/Bicep.LangServer/Configuration/BicepConfigChangeHandler.cs @@ -52,17 +52,17 @@ public void HandleBicepConfigChangeEvent(DocumentUri documentUri) } private void HandleBicepConfigOpenOrChangeEvent(DocumentUri documentUri) - => configurationManager.RefreshConfigCacheEntry(documentUri.ToUri()); + => configurationManager.RefreshConfigCacheEntry(documentUri.ToUriEncoded()); public void HandleBicepConfigSaveEvent(DocumentUri documentUri) { - if (configurationManager.RefreshConfigCacheEntry(documentUri.ToUri()) is {} update) + if (configurationManager.RefreshConfigCacheEntry(documentUri.ToUriEncoded()) is {} update) { TelemetryHelper.SendTelemetryOnBicepConfigChange(update.prevConfiguration, update.newConfiguration, linterRulesProvider, telemetryProvider); } } public void HandleBicepConfigCloseEvent(DocumentUri documentUri) - => configurationManager.RemoveConfigCacheEntry(documentUri.ToUri()); + => configurationManager.RemoveConfigCacheEntry(documentUri.ToUriEncoded()); } } diff --git a/src/Bicep.LangServer/Configuration/ConfigurationHelper.cs b/src/Bicep.LangServer/Configuration/ConfigurationHelper.cs index 0e21d2a9b9d..17782ec6e6e 100644 --- a/src/Bicep.LangServer/Configuration/ConfigurationHelper.cs +++ b/src/Bicep.LangServer/Configuration/ConfigurationHelper.cs @@ -30,7 +30,7 @@ public static bool TryGetConfiguration(IConfigurationManager configurationManage { try { - rootConfiguration = configurationManager.GetConfiguration(documentUri.ToUri()); + rootConfiguration = configurationManager.GetConfiguration(documentUri.ToUriEncoded()); return true; } catch(Exception e) diff --git a/src/Bicep.LangServer/Extensions/DocumentUriExtensions.cs b/src/Bicep.LangServer/Extensions/DocumentUriExtensions.cs new file mode 100644 index 00000000000..58940fd198d --- /dev/null +++ b/src/Bicep.LangServer/Extensions/DocumentUriExtensions.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using OmniSharp.Extensions.LanguageServer.Protocol; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static class DocumentUriExtensions + { + public static Uri ToUriEncoded(this DocumentUri documentUri) + { +#pragma warning disable RS0030 // Do not use banned APIs + return documentUri + .With(new() { Path = documentUri.Path.Replace("%", "%25") }) + .ToUri(); +#pragma warning restore RS0030 // Do not use banned APIs + } + } +} diff --git a/src/Bicep.LangServer/Handlers/BicepBuildCommandHandler.cs b/src/Bicep.LangServer/Handlers/BicepBuildCommandHandler.cs index 6ad9120513f..2e6efbdb37c 100644 --- a/src/Bicep.LangServer/Handlers/BicepBuildCommandHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepBuildCommandHandler.cs @@ -59,7 +59,7 @@ private async Task GenerateCompiledFileAndReturnBuildOutputMessage(strin return "Bicep build failed. The output 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(); + var fileUri = documentUri.ToUriEncoded(); var compilation = await new CompilationHelper(bicepCompiler, compilationManager).GetRefreshedCompilation(documentUri); diff --git a/src/Bicep.LangServer/Handlers/BicepBuildParamsCommandHandler.cs b/src/Bicep.LangServer/Handlers/BicepBuildParamsCommandHandler.cs index 901028dc3bc..d5dab97f599 100644 --- a/src/Bicep.LangServer/Handlers/BicepBuildParamsCommandHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepBuildParamsCommandHandler.cs @@ -62,7 +62,7 @@ private async Task GenerateCompiledParametersFileAndReturnOutputMessage( } var compilation = await new CompilationHelper(bicepCompiler, compilationManager).GetRefreshedCompilation(documentUri); - var fileUri = documentUri.ToUri(); + var fileUri = documentUri.ToUriEncoded(); var diagnosticsByFile = compilation.GetAllDiagnosticsByBicepFile().FirstOrDefault(x => x.Key.FileUri == fileUri); diff --git a/src/Bicep.LangServer/Handlers/BicepCompletionHandler.cs b/src/Bicep.LangServer/Handlers/BicepCompletionHandler.cs index d3e95345182..ee90c6e981e 100644 --- a/src/Bicep.LangServer/Handlers/BicepCompletionHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepCompletionHandler.cs @@ -11,6 +11,7 @@ using Bicep.LanguageServer.Completions; using Bicep.LanguageServer.Utils; using Microsoft.Extensions.Logging; +using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; @@ -36,7 +37,7 @@ public override async Task Handle(CompletionParams request, Canc { var completions = Enumerable.Empty(); - var featureProvider = featureProviderFactory.GetFeatureProvider(request.TextDocument.Uri.ToUri()); + var featureProvider = featureProviderFactory.GetFeatureProvider(request.TextDocument.Uri.ToUriEncoded()); var compilationContext = this.compilationManager.GetCompilation(request.TextDocument.Uri); if (compilationContext is null) { diff --git a/src/Bicep.LangServer/Handlers/BicepDefinitionHandler.cs b/src/Bicep.LangServer/Handlers/BicepDefinitionHandler.cs index 88f4bd69af8..83f0f2ec71f 100644 --- a/src/Bicep.LangServer/Handlers/BicepDefinitionHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepDefinitionHandler.cs @@ -110,7 +110,7 @@ private LocationOrLocationLinks HandleUnboundSymbolLocation(DefinitionParams req && matchingNodes[^3] is ModuleDeclarationSyntax moduleDeclarationSyntax && matchingNodes[^2] is StringSyntax stringToken && context.Compilation.SourceFileGrouping.TryGetSourceFile(moduleDeclarationSyntax) is ISourceFile sourceFile - && this.moduleDispatcher.TryGetModuleReference(moduleDeclarationSyntax, request.TextDocument.Uri.ToUri(), out var moduleReference, out _)) + && this.moduleDispatcher.TryGetModuleReference(moduleDeclarationSyntax, request.TextDocument.Uri.ToUriEncoded(), out var moduleReference, out _)) { // goto beginning of the module file. return GetFileDefinitionLocation( @@ -127,7 +127,7 @@ private LocationOrLocationLinks HandleUnboundSymbolLocation(DefinitionParams req && matchingNodes[^4] is CompileTimeImportDeclarationSyntax importDeclarationSyntax && matchingNodes[^2] is StringSyntax stringToken && context.Compilation.SourceFileGrouping.TryGetSourceFile(importDeclarationSyntax) is ISourceFile sourceFile - && this.moduleDispatcher.TryGetModuleReference(importDeclarationSyntax, request.TextDocument.Uri.ToUri(), out var moduleReference, out _)) + && this.moduleDispatcher.TryGetModuleReference(importDeclarationSyntax, request.TextDocument.Uri.ToUriEncoded(), out var moduleReference, out _)) { // goto beginning of the module file. return GetFileDefinitionLocation( diff --git a/src/Bicep.LangServer/Handlers/BicepDeploymentScopeRequestHandler.cs b/src/Bicep.LangServer/Handlers/BicepDeploymentScopeRequestHandler.cs index bc741bffdd1..f6698ac533e 100644 --- a/src/Bicep.LangServer/Handlers/BicepDeploymentScopeRequestHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepDeploymentScopeRequestHandler.cs @@ -81,7 +81,7 @@ public override async Task Handle(BicepDeploymentS private string GetCompiledFile(Compilation compilation, DocumentUri documentUri) { - var fileUri = documentUri.ToUri(); + var fileUri = documentUri.ToUriEncoded(); var diagnosticsByFile = compilation.GetAllDiagnosticsByBicepFile() .FirstOrDefault(x => x.Key.FileUri == fileUri); diff --git a/src/Bicep.LangServer/Handlers/BicepDeploymentStartCommandHandler.cs b/src/Bicep.LangServer/Handlers/BicepDeploymentStartCommandHandler.cs index f7a30de2ca9..e2ad58b3dcf 100644 --- a/src/Bicep.LangServer/Handlers/BicepDeploymentStartCommandHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepDeploymentStartCommandHandler.cs @@ -88,15 +88,15 @@ public override async Task Handle(BicepDeploymentS var credential = new CredentialFromTokenAndTimeStamp(request.token, request.expiresOnTimestamp); var armClient = armClientProvider.createArmClient(credential, default, options); - - //starting with empty valid json (that can be parsed) for deployments with no parameters + + //starting with empty valid json (that can be parsed) for deployments with no parameters string parametersFileJson = "{}"; - + if(request.parametersFilePath is { }) { - if (PathHelper.HasBicepparamsExension(DocumentUri.FromFileSystemPath(request.parametersFilePath).ToUri())) + if (PathHelper.HasBicepparamsExension(DocumentUri.FromFileSystemPath(request.parametersFilePath).ToUriEncoded())) { - //params file validation + //params file validation if (request.parametersFileUpdateOption != ParametersFileUpdateOption.None) { return new BicepDeploymentStartResponse(false, "Cannot create/overwrite/update parameter files when using a bicep parameters file", null); @@ -121,7 +121,7 @@ public override async Task Handle(BicepDeploymentS } else { - //request.parametersFileName only exists for a json parameter file + //request.parametersFileName only exists for a json parameter file //as it maybe need to create a file if none exits on disk if (request.parametersFileName is { }) { @@ -145,8 +145,8 @@ public override async Task Handle(BicepDeploymentS } } } - - //stringified json for params passed here + + //stringified json for params passed here var bicepDeploymentStartResponse = await deploymentHelper.StartDeploymentAsync( deploymentCollectionProvider, armClient, @@ -207,7 +207,7 @@ public async Task TryCompileBicepparamFile(string p return new BicepparamCompilationResult(true, paramsOutputBuffer.ToString()); } - public string ExtractParametersObjectValue(string JsonParametersContent) + public string ExtractParametersObjectValue(string JsonParametersContent) { var jObject = JObject.Parse(JsonParametersContent); var parameters = jObject["parameters"]; @@ -215,8 +215,8 @@ public string ExtractParametersObjectValue(string JsonParametersContent) if (parameters is not null) { return parameters.ToString(); - } - + } + //return original JSON if no "parameters" property found return jObject.ToString(); } diff --git a/src/Bicep.LangServer/Handlers/BicepDidChangeWatchedFilesHandler.cs b/src/Bicep.LangServer/Handlers/BicepDidChangeWatchedFilesHandler.cs index 8a79c4d5ff7..a7ee73b1813 100644 --- a/src/Bicep.LangServer/Handlers/BicepDidChangeWatchedFilesHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepDidChangeWatchedFilesHandler.cs @@ -10,6 +10,7 @@ using Bicep.LanguageServer.CompilationManager; using Bicep.LanguageServer.Configuration; using MediatR; +using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; @@ -35,10 +36,10 @@ public override Task Handle(DidChangeWatchedFilesParams request, Cancellat LanguageConstants.BicepConfigurationFileName, StringComparison.OrdinalIgnoreCase)); - // Refresh compilation of source files in workspace when local bicepconfig.json file is created, deleted or changed + // Refresh compilation of source files in workspace when local bicepconfig.json file is created, deleted or changed if (bicepConfigFileChangeEvents.Any()) { - Uri uri = bicepConfigFileChangeEvents.First().Uri.ToUri(); + Uri uri = bicepConfigFileChangeEvents.First().Uri.ToUriEncoded(); bicepConfigChangeHandler.RefreshCompilationOfSourceFilesInWorkspace(); } diff --git a/src/Bicep.LangServer/Handlers/BicepDocumentFormattingHandler.cs b/src/Bicep.LangServer/Handlers/BicepDocumentFormattingHandler.cs index 0aa3ce5daef..67bd3327325 100644 --- a/src/Bicep.LangServer/Handlers/BicepDocumentFormattingHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepDocumentFormattingHandler.cs @@ -14,6 +14,7 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using Bicep.Core.Features; using Bicep.Core.PrettyPrintV2; +using OmniSharp.Extensions.LanguageServer.Protocol; namespace Bicep.LanguageServer.Handlers { @@ -49,7 +50,7 @@ public BicepDocumentFormattingHandler( var lexingErrorLookup = context.Compilation.SourceFileGrouping.EntryPoint.LexingErrorLookup; var parsingErrorLookup = context.Compilation.SourceFileGrouping.EntryPoint.ParsingErrorLookup; - var featureProvider = this.featureProviderFactory.GetFeatureProvider(request.TextDocument.Uri.ToUri()); + var featureProvider = this.featureProviderFactory.GetFeatureProvider(request.TextDocument.Uri.ToUriEncoded()); if (featureProvider.PrettyPrintingEnabled) { diff --git a/src/Bicep.LangServer/Handlers/BicepForceModulesRestoreCommandHandler.cs b/src/Bicep.LangServer/Handlers/BicepForceModulesRestoreCommandHandler.cs index 188b3b6c32e..98dfe69c85b 100644 --- a/src/Bicep.LangServer/Handlers/BicepForceModulesRestoreCommandHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepForceModulesRestoreCommandHandler.cs @@ -55,7 +55,7 @@ public override Task Handle(string bicepFilePath, CancellationToken canc private async Task ForceModulesRestoreAndGenerateOutputMessage(DocumentUri documentUri) { - var fileUri = documentUri.ToUri(); + var fileUri = documentUri.ToUriEncoded(); SourceFileGrouping sourceFileGrouping = SourceFileGroupingBuilder.Build( this.fileResolver, diff --git a/src/Bicep.LangServer/Handlers/BicepGenerateParamsCommandHandler.cs b/src/Bicep.LangServer/Handlers/BicepGenerateParamsCommandHandler.cs index 756a4b1eeb3..a921c0eb5e8 100644 --- a/src/Bicep.LangServer/Handlers/BicepGenerateParamsCommandHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepGenerateParamsCommandHandler.cs @@ -68,7 +68,7 @@ private async Task GenerateCompiledParametersFileAndReturnOutputMessage( } var compilation = await new CompilationHelper(bicepCompiler, compilationManager).GetRefreshedCompilation(documentUri); - var fileUri = documentUri.ToUri(); + var fileUri = documentUri.ToUriEncoded(); var diagnosticsByFile = compilation.GetAllDiagnosticsByBicepFile() .FirstOrDefault(x => x.Key.FileUri == fileUri); diff --git a/src/Bicep.LangServer/Handlers/BicepHoverHandler.cs b/src/Bicep.LangServer/Handlers/BicepHoverHandler.cs index f2f0f84345a..8ecbcbf68a9 100644 --- a/src/Bicep.LangServer/Handlers/BicepHoverHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepHoverHandler.cs @@ -16,6 +16,7 @@ using Bicep.Core.TypeSystem; using Bicep.LanguageServer.Providers; using Bicep.LanguageServer.Utils; +using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; @@ -66,7 +67,7 @@ public BicepHoverHandler( { if (symbol.DeclaringSyntax is DecorableSyntax decorableSyntax && DescriptionHelper.TryGetFromDecorator( - result.Context.Compilation.GetEntrypointSemanticModel(), + result.Context.Compilation.GetEntrypointSemanticModel(), decorableSyntax) is { } description) { return description; @@ -127,7 +128,7 @@ public BicepHoverHandler( case ModuleSymbol module: return await GetModuleMarkdown(request, result, moduleDispatcher, moduleRegistryProvider, module); - + case TestSymbol test: return AsMarkdown(CodeBlockWithDescription($"test {test.Name}", TryGetDescriptionMarkdown(result, test))); case OutputSymbol output: @@ -173,10 +174,10 @@ public BicepHoverHandler( } private static async Task GetModuleMarkdown( - HoverParams request, - SymbolResolutionResult result, - IModuleDispatcher moduleDispatcher, - IModuleRegistryProvider moduleRegistryProvider, + HoverParams request, + SymbolResolutionResult result, + IModuleDispatcher moduleDispatcher, + IModuleRegistryProvider moduleRegistryProvider, ModuleSymbol module) { if (!SyntaxHelper.TryGetForeignTemplatePath(module.DeclaringModule, out var filePath, out _)) @@ -186,7 +187,7 @@ private static async Task GetModuleMarkdown( var descriptionLines = new List(); descriptionLines.Add(TryGetDescriptionMarkdown(result, module)); - var uri = request.TextDocument.Uri.ToUri(); + var uri = request.TextDocument.Uri.ToUriEncoded(); var registries = moduleRegistryProvider.Registries(uri); if (registries != null && diff --git a/src/Bicep.LangServer/Handlers/BicepRegistryCacheRequestHandler.cs b/src/Bicep.LangServer/Handlers/BicepRegistryCacheRequestHandler.cs index 8a3aa0c3a21..15d606452e4 100644 --- a/src/Bicep.LangServer/Handlers/BicepRegistryCacheRequestHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepRegistryCacheRequestHandler.cs @@ -6,6 +6,7 @@ using Bicep.Core.Registry; using MediatR; using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using System; using System.Threading; @@ -42,7 +43,7 @@ public Task Handle(BicepRegistryCacheParams request, // it indicates a code defect client or server-side. // In normal operation, the user should never see them regardless of how malformed their code is. - if (!moduleDispatcher.TryGetModuleReference(request.Target, request.TextDocument.Uri.ToUri(), out var moduleReference, out _)) + if (!moduleDispatcher.TryGetModuleReference(request.Target, request.TextDocument.Uri.ToUriEncoded(), out var moduleReference, out _)) { throw new InvalidOperationException( $"The client specified an invalid module reference '{request.Target}'."); diff --git a/src/Bicep.LangServer/Handlers/BicepTextDocumentSyncHandler.cs b/src/Bicep.LangServer/Handlers/BicepTextDocumentSyncHandler.cs index f0e586c0c00..0df24e99046 100644 --- a/src/Bicep.LangServer/Handlers/BicepTextDocumentSyncHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepTextDocumentSyncHandler.cs @@ -22,7 +22,7 @@ public class BicepTextDocumentSyncHandler : TextDocumentSyncHandlerBase private readonly ICompilationManager compilationManager; private readonly IBicepConfigChangeHandler bicepConfigChangeHandler; - public BicepTextDocumentSyncHandler(ICompilationManager compilationManager, IBicepConfigChangeHandler bicepConfigChangeHandler) + public BicepTextDocumentSyncHandler(ICompilationManager compilationManager, IBicepConfigChangeHandler bicepConfigChangeHandler) { this.bicepConfigChangeHandler = bicepConfigChangeHandler; this.compilationManager = compilationManager; @@ -35,7 +35,7 @@ public override TextDocumentAttributes GetTextDocumentAttributes(DocumentUri uri return new TextDocumentAttributes(uri, LanguageConstants.JsoncLanguageId); } - if(PathHelper.HasBicepparamsExension(uri.ToUri())) + if(PathHelper.HasBicepparamsExension(uri.ToUriEncoded())) { return new TextDocumentAttributes(uri, LanguageConstants.ParamsLanguageId); } diff --git a/src/Bicep.LangServer/Providers/BicepCompilationProvider.cs b/src/Bicep.LangServer/Providers/BicepCompilationProvider.cs index aef97074699..a34942a0f61 100644 --- a/src/Bicep.LangServer/Providers/BicepCompilationProvider.cs +++ b/src/Bicep.LangServer/Providers/BicepCompilationProvider.cs @@ -52,7 +52,7 @@ public CompilationContext Create( fileResolver, moduleDispatcher, workspace, - documentUri.ToUri(), + documentUri.ToUriEncoded(), featureProviderFactory); return this.CreateContext(sourceFileGrouping, modelLookup); } diff --git a/src/Bicep.LangServer/Utils/CompilationHelper.cs b/src/Bicep.LangServer/Utils/CompilationHelper.cs index bbe9811364b..570d34907f1 100644 --- a/src/Bicep.LangServer/Utils/CompilationHelper.cs +++ b/src/Bicep.LangServer/Utils/CompilationHelper.cs @@ -23,7 +23,7 @@ public CompilationHelper(BicepCompiler bicepCompiler, ICompilationManager compil public async Task GetRefreshedCompilation(DocumentUri documentUri) { // Bicep file could contain load functions like loadTextContent(..). We'll refresh compilation to detect changes in files referenced in load functions. - var fileUri = documentUri.ToUri(); + var fileUri = documentUri.ToUriEncoded(); compilationManager.RefreshCompilation(fileUri); var context = compilationManager.GetCompilation(documentUri); diff --git a/src/vs-bicep/Bicep.VSLanguageServerClient.UnitTests/MiddleLayerProviders/HandleGotoDefintionMiddleLayerTests.cs b/src/vs-bicep/Bicep.VSLanguageServerClient.UnitTests/MiddleLayerProviders/HandleGotoDefintionMiddleLayerTests.cs index 71a267e33ea..04b51d31fc0 100644 --- a/src/vs-bicep/Bicep.VSLanguageServerClient.UnitTests/MiddleLayerProviders/HandleGotoDefintionMiddleLayerTests.cs +++ b/src/vs-bicep/Bicep.VSLanguageServerClient.UnitTests/MiddleLayerProviders/HandleGotoDefintionMiddleLayerTests.cs @@ -34,7 +34,7 @@ public void GetVSLocations_WithValidLocation_ShouldReturnVSLocation() var vsLocation = handleGotoDefintionMiddleLayer.GetVSLocation(locationOrLocationLink); Assert.IsNotNull(vsLocation); - vsLocation.Uri.Should().Be(uri.ToUri()); + vsLocation.Uri.Should().Be(uri.ToUriEncoded()); var resultStart = vsLocation.Range.Start; var resultEnd = vsLocation.Range.End; @@ -74,7 +74,7 @@ public void GetVSLocations_WithValidLocationLink_ShouldReturnVSLocation() var vsLocation = handleGotoDefintionMiddleLayer.GetVSLocation(locationOrLocationLink); Assert.IsNotNull(vsLocation); - vsLocation.Uri.Should().Be(uri.ToUri()); + vsLocation.Uri.Should().Be(uri.ToUriEncoded()); var resultStart = vsLocation.Range.Start; var resultEnd = vsLocation.Range.End; diff --git a/src/vs-bicep/Bicep.VSLanguageServerClient/Extensions/DocumentUriExtensions.cs b/src/vs-bicep/Bicep.VSLanguageServerClient/Extensions/DocumentUriExtensions.cs new file mode 100644 index 00000000000..58940fd198d --- /dev/null +++ b/src/vs-bicep/Bicep.VSLanguageServerClient/Extensions/DocumentUriExtensions.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using OmniSharp.Extensions.LanguageServer.Protocol; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static class DocumentUriExtensions + { + public static Uri ToUriEncoded(this DocumentUri documentUri) + { +#pragma warning disable RS0030 // Do not use banned APIs + return documentUri + .With(new() { Path = documentUri.Path.Replace("%", "%25") }) + .ToUri(); +#pragma warning restore RS0030 // Do not use banned APIs + } + } +} diff --git a/src/vs-bicep/Bicep.VSLanguageServerClient/MiddleLayerProviders/HandleGotoDefintionMiddleLayer.cs b/src/vs-bicep/Bicep.VSLanguageServerClient/MiddleLayerProviders/HandleGotoDefintionMiddleLayer.cs index 1ef72fee262..cc7cab52d61 100644 --- a/src/vs-bicep/Bicep.VSLanguageServerClient/MiddleLayerProviders/HandleGotoDefintionMiddleLayer.cs +++ b/src/vs-bicep/Bicep.VSLanguageServerClient/MiddleLayerProviders/HandleGotoDefintionMiddleLayer.cs @@ -95,7 +95,7 @@ private VSLocation GetVSLocation(DocumentUri documentUri, OmniSharpRange omniSha End = new VSPosition(end.Line, end.Character) }; - return new VSLocation() { Uri = documentUri.ToUri(), Range = vsRange }; + return new VSLocation() { Uri = documentUri.ToUriEncoded(), Range = vsRange }; } } }