Skip to content

Commit

Permalink
Fine-tune priorities for module completions (#10262)
Browse files Browse the repository at this point in the history
* Fine-tune priorities for module completion

* Update src/Bicep.LangServer/Completions/ModuleReferenceCompletionProvider.cs

Co-authored-by: Shenglong Li <shenglong.li@outlook.com>

* fix typo bug

* update tests

* fix merge

* fix test failure from merge

* Update test baselines

---------

Co-authored-by: Stephen Weatherford <Stephen.Weatherford.com>
Co-authored-by: Shenglong Li <shenglong.li@outlook.com>
Co-authored-by: Bicep Automation <bicep@noreply.github.com>
  • Loading branch information
3 people committed Mar 31, 2023
1 parent 401f015 commit 9f50b49
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@
{
"label": "br/",
"kind": "reference",
"detail": "Bicep registry schema name",
"detail": "Bicep registry (alias)",
"deprecated": false,
"preselect": false,
"sortText": "1_br/",
"sortText": "90_br/",
"filterText": "'br/$0'",
"insertTextFormat": "snippet",
"insertTextMode": "adjustIndentation",
Expand All @@ -71,10 +71,10 @@
{
"label": "br:",
"kind": "reference",
"detail": "Bicep registry schema name",
"detail": "Bicep registry",
"deprecated": false,
"preselect": false,
"sortText": "0_br:",
"sortText": "92_br:",
"filterText": "'br:$0'",
"insertTextFormat": "snippet",
"insertTextMode": "adjustIndentation",
Expand Down Expand Up @@ -282,10 +282,10 @@
{
"label": "ts:",
"kind": "reference",
"detail": "Template spec schema name",
"detail": "Template spec",
"deprecated": false,
"preselect": false,
"sortText": "0_ts:",
"sortText": "92_ts:",
"filterText": "'ts:$0'",
"insertTextFormat": "snippet",
"insertTextMode": "adjustIndentation",
Expand Down
8 changes: 4 additions & 4 deletions src/Bicep.LangServer.IntegrationTests/CompletionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1809,13 +1809,13 @@ public async Task ModuleCompletionsShouldNotBeUrlEscaped()
var completions = await file.RequestCompletion(cursor);

completions.OrderBy(x => x.SortText).Should().SatisfyRespectively(
x => x.Label.Should().Be("br:"),
x => x.Label.Should().Be("ts:"),
x => x.Label.Should().Be("already%20escaped.bicep"),
x => x.Label.Should().Be("br/"),
x => x.Label.Should().Be("percentage%file.bicep"),
x => x.Label.Should().Be("../"),
x => x.Label.Should().Be("folder with space/")
x => x.Label.Should().Be("folder with space/"),
x => x.Label.Should().Be("br/"),
x => x.Label.Should().Be("br:"),
x => x.Label.Should().Be("ts:")
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public async Task GetFilteredCompletions_WithBicepRegistryAndTemplateSpecShemaCo
c.Kind == CompletionItemKind.Reference &&
c.InsertTextFormat == InsertTextFormat.Snippet &&
c.InsertText == null &&
c.Detail == "Bicep registry schema name" &&
c.Detail == "Bicep registry" &&
c.TextEdit!.TextEdit!.NewText == "'br:$0'" &&
c.TextEdit.TextEdit.Range.Start.Line == 0 &&
c.TextEdit.TextEdit.Range.Start.Character == 12 &&
Expand All @@ -70,7 +70,7 @@ public async Task GetFilteredCompletions_WithBicepRegistryAndTemplateSpecShemaCo
c.Kind == CompletionItemKind.Reference &&
c.InsertTextFormat == InsertTextFormat.Snippet &&
c.InsertText == null &&
c.Detail == "Bicep registry schema name" &&
c.Detail == "Bicep registry (alias)" &&
c.TextEdit!.TextEdit!.NewText == "'br/$0'" &&
c.TextEdit.TextEdit.Range.Start.Line == 0 &&
c.TextEdit.TextEdit.Range.Start.Character == 12 &&
Expand All @@ -82,7 +82,7 @@ public async Task GetFilteredCompletions_WithBicepRegistryAndTemplateSpecShemaCo
c.Kind == CompletionItemKind.Reference &&
c.InsertTextFormat == InsertTextFormat.Snippet &&
c.InsertText == null &&
c.Detail == "Template spec schema name" &&
c.Detail == "Template spec" &&
c.TextEdit!.TextEdit!.NewText == "'ts:$0'" &&
c.TextEdit.TextEdit.Range.Start.Line == 0 &&
c.TextEdit.TextEdit.Range.Start.Character == 12 &&
Expand Down Expand Up @@ -125,7 +125,7 @@ public async Task GetFilteredCompletions_WithBicepRegistryAndTemplateSpecShemaCo
c.Kind == CompletionItemKind.Reference &&
c.InsertTextFormat == InsertTextFormat.Snippet &&
c.InsertText == null &&
c.Detail == "Bicep registry schema name" &&
c.Detail == "Bicep registry" &&
c.TextEdit!.TextEdit!.NewText == "'br:$0'" &&
c.TextEdit.TextEdit.Range.Start.Line == 0 &&
c.TextEdit.TextEdit.Range.Start.Character == 12 &&
Expand All @@ -137,7 +137,7 @@ public async Task GetFilteredCompletions_WithBicepRegistryAndTemplateSpecShemaCo
c.Kind == CompletionItemKind.Reference &&
c.InsertTextFormat == InsertTextFormat.Snippet &&
c.InsertText == null &&
c.Detail == "Bicep registry schema name" &&
c.Detail == "Bicep registry (alias)" &&
c.TextEdit!.TextEdit!.NewText == "'br/$0'" &&
c.TextEdit.TextEdit.Range.Start.Line == 0 &&
c.TextEdit.TextEdit.Range.Start.Character == 12 &&
Expand All @@ -149,7 +149,7 @@ public async Task GetFilteredCompletions_WithBicepRegistryAndTemplateSpecShemaCo
c.Kind == CompletionItemKind.Reference &&
c.InsertTextFormat == InsertTextFormat.Snippet &&
c.InsertText == null &&
c.Detail == "Template spec schema name" &&
c.Detail == "Template spec" &&
c.TextEdit!.TextEdit!.NewText == "'ts:$0'" &&
c.TextEdit.TextEdit.Range.Start.Line == 0 &&
c.TextEdit.TextEdit.Range.Start.Character == 12 &&
Expand All @@ -161,7 +161,7 @@ public async Task GetFilteredCompletions_WithBicepRegistryAndTemplateSpecShemaCo
c.Kind == CompletionItemKind.Reference &&
c.InsertTextFormat == InsertTextFormat.Snippet &&
c.InsertText == null &&
c.Detail == "Template spec schema name" &&
c.Detail == "Template spec (alias)" &&
c.TextEdit!.TextEdit!.NewText == "'ts/$0'" &&
c.TextEdit.TextEdit.Range.Start.Line == 0 &&
c.TextEdit.TextEdit.Range.Start.Character == 12 &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,34 @@

namespace Bicep.LanguageServer.Completions
{
/// <summary>
/// Provides completions for remote (public or private) module references, e.g. br/public:modulePath:version
/// </summary>
public class ModuleReferenceCompletionProvider : IModuleReferenceCompletionProvider
{
private readonly IAzureContainerRegistryNamesProvider azureContainerRegistryNamesProvider;
private readonly IConfigurationManager configurationManager;
private readonly IPublicRegistryModuleMetadataProvider publicRegistryModuleMetadataProvider;
private readonly ISettingsProvider settingsProvider;
private readonly ITelemetryProvider telemetryProvider;
private static readonly ImmutableDictionary<string, (string, CompletionPriority)> DefaultSchemaCompletionLabelsWithDetails = new Dictionary<string, (string, CompletionPriority)>()

private enum ModuleCompletionPriority
{
{"br:", ("Bicep registry schema name", CompletionPriority.VeryHigh) },
{"br/", ("Bicep registry schema name", CompletionPriority.High) },
{"ts:", ("Template spec schema name", CompletionPriority.VeryHigh) }
Alias = 0, // br/[alias], ts/[alias]
Default = 1,
FullPath = 2, // br:, ts:
}

private const string ModuleFullPathCompletionLabel = "Bicep registry";
private const string ModuleAliasCompletionLabel = "Bicep registry (alias)";
private const string TemplateSpecFullPathCompletionLabel = "Template spec";
private const string TemplateSpecAliasCompletionLabel = "Template spec (alias)";

private static readonly ImmutableDictionary<string, (string, ModuleCompletionPriority)> DefaultSchemaCompletionLabelsWithDetails = new Dictionary<string, (string, ModuleCompletionPriority)>()
{
{"br:", (ModuleFullPathCompletionLabel, ModuleCompletionPriority.FullPath) },
{"br/", (ModuleAliasCompletionLabel, ModuleCompletionPriority.Alias) },
{"ts:", (TemplateSpecFullPathCompletionLabel, ModuleCompletionPriority.FullPath) }
}.ToImmutableDictionary();

private static readonly Regex ModuleRegistryWithoutAlias = new Regex(@"'br:(?<registry>(.*?))/'?$", RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);
Expand Down Expand Up @@ -91,15 +107,15 @@ private IEnumerable<CompletionItem> GetBicepRegistryAndTemplateSpecShemaCompleti
var completionLabelsWithDetails = DefaultSchemaCompletionLabelsWithDetails;
if (templateSpecModuleAliases.Any())
{
completionLabelsWithDetails = completionLabelsWithDetails.Add("ts/", ("Template spec schema name", CompletionPriority.High));
completionLabelsWithDetails = completionLabelsWithDetails.Add("ts/", (TemplateSpecAliasCompletionLabel, ModuleCompletionPriority.Alias));
}

List<CompletionItem> completionItems = new List<CompletionItem>();
foreach (var kvp in completionLabelsWithDetails)
{
var text = kvp.Key;
var insertionText = $"'{text}$0'";
(var details, CompletionPriority completionPriority) = kvp.Value;
(var details, ModuleCompletionPriority completionPriority) = kvp.Value;

var completionItem = CompletionItemBuilder.Create(CompletionItemKind.Reference, text)
.WithFilterText(insertionText)
Expand Down Expand Up @@ -284,6 +300,7 @@ private async Task<IEnumerable<CompletionItem>> GetMCRPathCompletionFromBicepCon
break;
}

// br/[alias]:<cursor>
if (registry.Equals(MCRRegistry, StringComparison.Ordinal) &&
replacementTextWithTrimmedEnd.Equals($"'br/{kvp.Key}:"))
{
Expand All @@ -301,6 +318,7 @@ private async Task<IEnumerable<CompletionItem>> GetMCRPathCompletionFromBicepCon
// }
if (modulePath is null)
{
// Completions are e.g. br/[alias]/bicep/[module]
if (replacementTextWithTrimmedEnd.Equals($"'br/{kvp.Key}:", StringComparison.Ordinal))
{
var moduleNames = await publicRegistryModuleMetadataProvider.GetModuleNames();
Expand All @@ -312,7 +330,7 @@ private async Task<IEnumerable<CompletionItem>> GetMCRPathCompletionFromBicepCon
var completionItem = CompletionItemBuilder.Create(CompletionItemKind.Snippet, label)
.WithSnippetEdit(context.ReplacementRange, insertText)
.WithFilterText(insertText)
.WithSortText(GetSortText(label, CompletionPriority.High))
.WithSortText(GetSortText(label, ModuleCompletionPriority.Alias))
.Build();

completions.Add(completionItem);
Expand All @@ -337,6 +355,7 @@ private async Task<IEnumerable<CompletionItem>> GetMCRPathCompletionFromBicepCon
continue;
}

// Completions are e.g. br/[alias]/[module]
var modulePathWithoutBicepKeyword = modulePath.Substring("bicep/".Length);
var moduleNames = await publicRegistryModuleMetadataProvider.GetModuleNames();

Expand All @@ -356,7 +375,7 @@ private async Task<IEnumerable<CompletionItem>> GetMCRPathCompletionFromBicepCon
var completionItem = CompletionItemBuilder.Create(CompletionItemKind.Snippet, label)
.WithSnippetEdit(context.ReplacementRange, insertText)
.WithFilterText(insertText)
.WithSortText(GetSortText(label, CompletionPriority.High))
.WithSortText(GetSortText(label, ModuleCompletionPriority.Alias))
.Build();
completions.Add(completionItem);
}
Expand Down Expand Up @@ -420,7 +439,7 @@ private IEnumerable<CompletionItem> GetACRPartialPathCompletionsFromBicepConfig(
var completionItem = CompletionItemBuilder.Create(CompletionItemKind.Snippet, modulePath)
.WithSnippetEdit(context.ReplacementRange, insertText)
.WithFilterText(insertText)
.WithSortText(GetSortText(modulePath, CompletionPriority.High))
.WithSortText(GetSortText(modulePath))
.Build();
completions.Add(completionItem);
}
Expand All @@ -445,7 +464,7 @@ private async Task<IEnumerable<CompletionItem>> GetPublicMCRPathCompletions(stri
var completionItem = CompletionItemBuilder.Create(CompletionItemKind.Snippet, moduleName)
.WithSnippetEdit(context.ReplacementRange, insertText)
.WithFilterText(insertText)
.WithSortText(GetSortText(moduleName, CompletionPriority.High))
.WithSortText(GetSortText(moduleName))
.Build();

completions.Add(completionItem);
Expand Down Expand Up @@ -480,7 +499,7 @@ private async Task<IEnumerable<CompletionItem>> GetRegistryCompletions(BicepComp
var completionItem = CompletionItemBuilder.Create(CompletionItemKind.Snippet, alias)
.WithFilterText(insertText)
.WithSnippetEdit(context.ReplacementRange, insertText)
.WithSortText(GetSortText(alias, CompletionPriority.High))
.WithSortText(GetSortText(alias))
.Build();
completions.Add(completionItem);
}
Expand All @@ -492,7 +511,7 @@ private async Task<IEnumerable<CompletionItem>> GetRegistryCompletions(BicepComp
var mcrCompletionItem = CompletionItemBuilder.Create(CompletionItemKind.Snippet, label)
.WithFilterText(insertText)
.WithSnippetEdit(context.ReplacementRange, insertText)
.WithSortText(GetSortText(label, CompletionPriority.High))
.WithSortText(GetSortText(label))
.Build();

completions.Add(mcrCompletionItem);
Expand Down Expand Up @@ -532,7 +551,7 @@ private async Task<IEnumerable<CompletionItem>> GetACRModuleRegistriesCompletion
var completionItem = CompletionItemBuilder.Create(CompletionItemKind.Snippet, registryName)
.WithFilterText(insertText)
.WithSnippetEdit(context.ReplacementRange, insertText)
.WithSortText(GetSortText(registryName, CompletionPriority.Medium))
.WithSortText(GetSortText(registryName, ModuleCompletionPriority.FullPath))
.Build();
completions.Add(completionItem);
}
Expand All @@ -559,7 +578,7 @@ private IEnumerable<CompletionItem> GetACRModuleRegistriesCompletionsFromBicepCo
var completionItem = CompletionItemBuilder.Create(CompletionItemKind.Snippet, label)
.WithFilterText(insertText)
.WithSnippetEdit(context.ReplacementRange, insertText)
.WithSortText(GetSortText(label, CompletionPriority.High))
.WithSortText(GetSortText(label))
.Build();
completions.Add(completionItem);

Expand All @@ -573,6 +592,10 @@ private IEnumerable<CompletionItem> GetACRModuleRegistriesCompletionsFromBicepCo

private static string GetSortText(string label, int priority) => $"{priority}_{label}";

private static string GetSortText(string label, CompletionPriority priority) => $"{(int)priority}_{label}";
private static string GetSortText(string label, ModuleCompletionPriority priority = ModuleCompletionPriority.Default)
{
// We want all module completion priorities to come after other completions (e.g. local module paths), so we start with "9"
return $"9{(int)priority}_{label}";
}
}
}

0 comments on commit 9f50b49

Please sign in to comment.