Skip to content

Commit

Permalink
Support partial public registry completions (#15646)
Browse files Browse the repository at this point in the history
Add support for typing a partial path and looking for completions:


![image](https://github.com/user-attachments/assets/1116df28-c0e8-4823-a86e-471b9763ca54)
###### Microsoft Reviewers: [Open in
CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/Azure/bicep/pull/15646)
  • Loading branch information
anthony-c-martin authored Nov 21, 2024
1 parent cd32858 commit dbc2429
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 209 deletions.
3 changes: 3 additions & 0 deletions src/Bicep.Core.UnitTests/BicepTestConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ public static IModuleDispatcher CreateModuleDispatcher(IServiceProvider services

public static readonly IModuleRestoreScheduler ModuleRestoreScheduler = CreateMockModuleRestoreScheduler();

public static RootConfiguration GetConfiguration(string contents)
=> RootConfiguration.Bind(IConfigurationManager.BuiltInConfigurationElement.Merge(JsonElementFactory.CreateElement(contents)));

public static RootConfiguration CreateMockConfiguration(Dictionary<string, object>? customConfigurationData = null, string? configFilePath = null)
{
var configurationData = new Dictionary<string, object>
Expand Down
2 changes: 1 addition & 1 deletion src/Bicep.Core/Configuration/IConfigurationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public interface IConfigurationManager
public static IConfigurationManager WithStaticConfiguration(RootConfiguration configuration)
=> new ConstantConfigurationManager(configuration);

protected static readonly JsonElement BuiltInConfigurationElement = GetBuiltInConfigurationElement();
static readonly JsonElement BuiltInConfigurationElement = GetBuiltInConfigurationElement();

private static readonly Lazy<RootConfiguration> BuiltInConfigurationLazy =
new(() => RootConfiguration.Bind(BuiltInConfigurationElement));
Expand Down
81 changes: 49 additions & 32 deletions src/Bicep.LangServer.IntegrationTests/CompletionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4128,19 +4128,9 @@ public async Task ModuleRegistryReferenceCompletions_GetCompletionsForFolderInsi
[DataRow("using 'br/public:|", BicepSourceFileKind.ParamsFile)]
public async Task ModuleRegistryReferenceCompletions_GetPathCompletions(string inputWithCursors, BicepSourceFileKind kind)
{
var testOutputPath = FileHelper.GetUniqueTestOutputPath(TestContext);
var (text, cursor) = ParserHelper.GetFileWithSingleCursor(inputWithCursors, '|');

var fileName = kind switch
{
BicepSourceFileKind.BicepFile => "main.bicep",
BicepSourceFileKind.ParamsFile => "main.bicepparam",
_ => throw new InvalidOperationException(),
};
var mainBicepFilePath = FileHelper.SaveResultFile(TestContext, fileName, text, testOutputPath);
var mainUri = DocumentUri.FromFileSystemPath(mainBicepFilePath);

FileHelper.SaveResultFile(TestContext, "groups.bicep", string.Empty, Path.Combine(testOutputPath, "br"));
var extension = kind == BicepSourceFileKind.ParamsFile ? "bicepparam" : "bicep";
var (fileText, cursor) = ParserHelper.GetFileWithSingleCursor(inputWithCursors, '|');
var fileUri = new Uri($"file:///{Guid.NewGuid():D}/{TestContext.TestName}/main.{extension}");

var settingsProvider = StrictMock.Of<ISettingsProvider>();
settingsProvider.Setup(x => x.GetSetting(LangServerConstants.GetAllAzureContainerRegistriesForCompletionsSetting)).Returns(false);
Expand All @@ -4151,11 +4141,10 @@ public async Task ModuleRegistryReferenceCompletions_GetPathCompletions(string i
using var helper = await MultiFileLanguageServerHelper.StartLanguageServer(
TestContext,
services => services
.AddSingleton<IPublicRegistryModuleMetadataProvider>(publicRegistryModuleMetadataProvider.Object)
.AddSingleton<ISettingsProvider>(settingsProvider.Object)
.WithFileResolver(new FileResolver(new LocalFileSystem())));
.AddSingleton(publicRegistryModuleMetadataProvider.Object)
.AddSingleton(settingsProvider.Object));

var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUriEncoded(), text);
var file = await new ServerRequestHelper(TestContext, helper).OpenFile(fileUri, fileText);
var completions = await file.RequestCompletion(cursor);

completions.Count().Should().Be(2);
Expand All @@ -4174,39 +4163,67 @@ public async Task ModuleRegistryReferenceCompletions_GetPathCompletions(string i
[DataRow("using 'br:mcr.microsoft.com/bicep/app/dapr-containerapp:|", BicepSourceFileKind.ParamsFile)]
public async Task ModuleRegistryReferenceCompletions_GetVersionCompletions(string inputWithCursors, BicepSourceFileKind kind)
{
var testOutputPath = FileHelper.GetUniqueTestOutputPath(TestContext);
var (text, cursor) = ParserHelper.GetFileWithSingleCursor(inputWithCursors, '|');

var fileName = kind switch
{
BicepSourceFileKind.BicepFile => "main.bicep",
BicepSourceFileKind.ParamsFile => "main.bicepparam",
_ => throw new InvalidOperationException(),
};
var mainBicepFilePath = FileHelper.SaveResultFile(TestContext, fileName, text, testOutputPath);
var mainUri = DocumentUri.FromFileSystemPath(mainBicepFilePath);
var extension = kind == BicepSourceFileKind.ParamsFile ? "bicepparam" : "bicep";
var (fileText, cursor) = ParserHelper.GetFileWithSingleCursor(inputWithCursors, '|');
var fileUri = new Uri($"file:///{Guid.NewGuid():D}/{TestContext.TestName}/main.{extension}");

var settingsProvider = StrictMock.Of<ISettingsProvider>();
settingsProvider.Setup(x => x.GetSetting(LangServerConstants.GetAllAzureContainerRegistriesForCompletionsSetting)).Returns(false);

var publicRegistryModuleMetadataProvider = StrictMock.Of<IPublicRegistryModuleMetadataProvider>();
publicRegistryModuleMetadataProvider.Setup(x => x.GetModulesMetadata()).Returns([new("app/dapr-containerapp", "d1", "contoso.com/help1")]);
publicRegistryModuleMetadataProvider.Setup(x => x.GetModuleVersionsMetadata("app/dapr-containerapp")).Returns([new("1.0.2", "d1", "contoso.com/help1"), new("1.0.1", null, null)]);
publicRegistryModuleMetadataProvider.Setup(x => x.GetModuleVersionsMetadata("app/dapr-containerapp")).Returns([new("1.0.2", "d1", "contoso.com/help1"), new("1.0.1", null, null)]);

using var helper = await MultiFileLanguageServerHelper.StartLanguageServer(
TestContext,
services => services
.AddSingleton<IPublicRegistryModuleMetadataProvider>(publicRegistryModuleMetadataProvider.Object)
.AddSingleton<ISettingsProvider>(settingsProvider.Object)
.WithFileResolver(new FileResolver(new LocalFileSystem())));
.AddSingleton(publicRegistryModuleMetadataProvider.Object)
.AddSingleton(settingsProvider.Object));

var file = await new ServerRequestHelper(TestContext, helper).OpenFile(mainUri.ToUriEncoded(), text);
var file = await new ServerRequestHelper(TestContext, helper).OpenFile(fileUri, fileText);
var completions = await file.RequestCompletion(cursor);

completions.Count().Should().Be(2);
completions.Should().Contain(x => x.Label == "1.0.1" && x.SortText == "0001" && x.Kind == CompletionItemKind.Snippet && x.Detail == null && x.Documentation == null);
completions.Should().Contain(x => x.Label == "1.0.2" && x.SortText == "0000" && x.Kind == CompletionItemKind.Snippet && x.Detail == "d1" && x.Documentation!.MarkupContent!.Value == "[View Documentation](contoso.com/help1)");
}

[TestMethod]
[DataRow("module test 'br:mcr.microsoft.com/bicep/foo|'", BicepSourceFileKind.BicepFile)]
[DataRow("module test 'br:mcr.microsoft.com/bicep/foo|", BicepSourceFileKind.BicepFile)]
[DataRow("module test 'br/public:foo|'", BicepSourceFileKind.BicepFile)]
[DataRow("module test 'br/public:foo|", BicepSourceFileKind.BicepFile)]
[DataRow("using 'br:mcr.microsoft.com/bicep/foo|'", BicepSourceFileKind.ParamsFile)]
[DataRow("using 'br:mcr.microsoft.com/bicep/foo|", BicepSourceFileKind.ParamsFile)]
[DataRow("using 'br/public:foo|'", BicepSourceFileKind.ParamsFile)]
[DataRow("using 'br/public:foo|", BicepSourceFileKind.ParamsFile)]
public async Task Public_registry_completions_support_prefix_matching(string text, BicepSourceFileKind kind)
{
var extension = kind == BicepSourceFileKind.ParamsFile ? "bicepparam" : "bicep";
var (fileText, cursor) = ParserHelper.GetFileWithSingleCursor(text, '|');
var fileUri = new Uri($"file:///{Guid.NewGuid():D}/{TestContext.TestName}/main.{extension}");

var settingsProvider = StrictMock.Of<ISettingsProvider>();
settingsProvider.Setup(x => x.GetSetting(LangServerConstants.GetAllAzureContainerRegistriesForCompletionsSetting)).Returns(false);

var publicRegistryModuleMetadataProvider = StrictMock.Of<IPublicRegistryModuleMetadataProvider>();
publicRegistryModuleMetadataProvider.Setup(x => x.GetModulesMetadata()).Returns([new("foo/bar", "d1", "contoso.com/help1"), new("food/bar", "d2", "contoso.com/help2"), new("bar/bar", "d2", "contoso.com/help2")]);

using var helper = await MultiFileLanguageServerHelper.StartLanguageServer(
TestContext,
services => services
.AddSingleton(publicRegistryModuleMetadataProvider.Object)
.AddSingleton(settingsProvider.Object));

var file = await new ServerRequestHelper(TestContext, helper).OpenFile(fileUri, fileText);
var completions = await file.RequestCompletion(cursor);

completions.Count().Should().Be(2);
completions.Should().Contain(x => x.Label == "foo/bar");
completions.Should().Contain(x => x.Label == "food/bar");
}

[DataTestMethod]
[DataRow("var arr1 = [|]")]
[DataRow("param arr array = [|]")]
Expand Down
25 changes: 3 additions & 22 deletions src/Bicep.LangServer.UnitTests/BicepCompilationManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -724,11 +724,8 @@ public void GetLinterStateTelemetryOnBicepFileOpen_ShouldReturnTelemetryEvent()
}
}
}";
var fileExplorer = new FileSystemFileExplorer(new LocalFileSystem());
var configurationManager = new ConfigurationManager(fileExplorer);
var testOutputPath = FileHelper.GetUniqueTestOutputPath(TestContext);

var rootConfiguration = GetRootConfiguration(testOutputPath, bicepConfigFileContents, configurationManager);
var rootConfiguration = BicepTestConstants.GetConfiguration(bicepConfigFileContents);

var telemetryEvent = compilationManager.GetLinterStateTelemetryOnBicepFileOpen(rootConfiguration);

Expand Down Expand Up @@ -777,11 +774,7 @@ public void GetLinterStateTelemetryOnBicepFileOpen_WithOverallLinterStateDisable
}
}
}";
var fileExplorer = new FileSystemFileExplorer(new LocalFileSystem());
var configurationManager = new ConfigurationManager(fileExplorer);
var testOutputPath = FileHelper.GetUniqueTestOutputPath(TestContext);

var rootConfiguration = GetRootConfiguration(testOutputPath, bicepConfigFileContents, configurationManager);
var rootConfiguration = BicepTestConstants.GetConfiguration(bicepConfigFileContents);

var telemetryEvent = compilationManager.GetLinterStateTelemetryOnBicepFileOpen(rootConfiguration);

Expand All @@ -801,11 +794,7 @@ public void GetLinterStateTelemetryOnBicepFileOpen_WithNoContents_ShouldUseDefau
var compilationManager = CreateBicepCompilationManager();

var bicepConfigFileContents = @"{}";
var fileExplorer = new FileSystemFileExplorer(new LocalFileSystem());
var configurationManager = new ConfigurationManager(fileExplorer);
var testOutputPath = FileHelper.GetUniqueTestOutputPath(TestContext);

var rootConfiguration = GetRootConfiguration(testOutputPath, bicepConfigFileContents, configurationManager);
var rootConfiguration = BicepTestConstants.GetConfiguration(bicepConfigFileContents);

var telemetryEvent = compilationManager.GetLinterStateTelemetryOnBicepFileOpen(rootConfiguration);

Expand Down Expand Up @@ -914,14 +903,6 @@ param intParam int
telemetryEvent.Properties.Should().Contain(properties);
}

private RootConfiguration GetRootConfiguration(string testOutputPath, string bicepConfigContents, ConfigurationManager configurationManager)
{
var bicepConfigFilePath = FileHelper.SaveResultFile(TestContext, "bicepconfig.json", bicepConfigContents, testOutputPath);
var bicepConfigUri = DocumentUri.FromFileSystemPath(bicepConfigFilePath);

return configurationManager.GetConfiguration(bicepConfigUri.ToUriEncoded());
}

private BicepCompilationManager CreateBicepCompilationManager()
{
PublishDiagnosticsParams? receivedParams = null;
Expand Down
Loading

0 comments on commit dbc2429

Please sign in to comment.