-
Notifications
You must be signed in to change notification settings - Fork 756
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Recognize common keywords for resource type completions
- Loading branch information
1 parent
88b03d4
commit 8ff24d3
Showing
6 changed files
with
230 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
src/Bicep.LangServer.UnitTests/Completions/ResourceTypeSearchKeywordsTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Bicep.Core.Resources; | ||
using Bicep.LanguageServer.Completions; | ||
using FluentAssertions; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using OmniSharp.Extensions.LanguageServer.Protocol.Models; | ||
|
||
namespace Bicep.LangServer.UnitTests.Completions | ||
{ | ||
[TestClass] | ||
public class ResourceTypeSearchKeywordsTests | ||
{ | ||
[DataRow("Microsoft.Web/sites", "'appservice,webapp,function,microsoft.web/sites'")] | ||
[DataRow("microsoft.web/sites", "'appservice,webapp,function,microsoft.web/sites'")] | ||
[DataRow("microsoft.app/abc", "'containerapp,microsoft.app/abc'")] | ||
[DataRow("Microsoft.ContainerService/managedClusters", "'aks,kubernetes,k8s,cluster,microsoft.containerservice/managedclusters'")] | ||
[DataRow("toplevel1", "'top level keyword,toplevel1'")] | ||
[DataRow("toplevel1/secondlevel1", "'top level keyword,toplevel1/secondlevel1'")] | ||
[DataRow("toplevel1/secondlevel2", "'top level keyword,toplevel1/secondlevel2'")] | ||
[DataRow("toplevel1/secondlevel1/thirdlevel", "'top level keyword,toplevel1/secondlevel1/thirdlevel'")] | ||
[DataRow("toplevel2", null)] | ||
[DataRow("toplevel2/secondlevel1", "'second level keyword,toplevel2/secondlevel1'")] | ||
[DataRow("toplevel2/secondlevel2", null)] | ||
[DataRow("toplevel2/secondlevel2/thirdlevel", null)] | ||
[DataRow("toplevel2/secondlevel1/thirdlevel", "'second level keyword,toplevel2/secondlevel1/thirdlevel'")] | ||
|
||
[DataTestMethod] | ||
public void TryGetResourceTypeFilterText(string resourceType, string? expectedFilter) | ||
{ | ||
var sut = new ResourceTypeSearchKeywords(new Dictionary<string, string[]> | ||
{ | ||
["Microsoft.Web/sites"] = ["appservice", "webapp", "function"], | ||
["Microsoft.Web/serverFarms"] = ["asp", "appserviceplan", "hostingplan"], | ||
["MICROSOFT.APP"] = ["containerapp"], | ||
["Microsoft.ContainerService"] = ["aks", "kubernetes", "k8s", "cluster"], | ||
["Microsoft.Authorization/roleAssignments"] = ["rbac"], | ||
["toplevel1"] = ["top level keyword"], | ||
["toplevel2/secondlevel1"] = ["second level keyword"], | ||
}); | ||
|
||
var result = sut.TryGetResourceTypeFilterText(new ResourceTypeReference(resourceType, "2020-06-01")); | ||
|
||
result.Should().Be(expectedFilter); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
src/Bicep.LangServer/Completions/ResourceTypeSearchKeywords.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Bicep.Core.Parsing; | ||
using Bicep.Core.Resources; | ||
|
||
namespace Bicep.LanguageServer.Completions | ||
{ | ||
public class ResourceTypeSearchKeywords | ||
{ | ||
private ImmutableDictionary<string, string[]> keywordsMap; | ||
|
||
public ResourceTypeSearchKeywords() : this | ||
(new Dictionary<string, string[]>() | ||
{ | ||
// Keys must be in the form 'xxx' or 'xxx/yyy' - 'xxx' matches 'xxx' and 'xxx/*', 'xxx/yyy' matches 'xxx/yyy' and 'xxx/yyy/*' | ||
// Key casing doesn't matter | ||
["Microsoft.Web/sites"] = ["appservice", "webapp", "function"], | ||
["Microsoft.Web/serverFarms"] = ["asp", "appserviceplan", "hostingplan"], | ||
["Microsoft.App"] = ["containerapp"], | ||
["Microsoft.ContainerService"] = ["aks", "kubernetes", "k8s", "cluster"], | ||
["Microsoft.Authorization/roleAssignments"] = ["rbac"], | ||
}) | ||
{ | ||
} | ||
|
||
public ResourceTypeSearchKeywords(IDictionary<string, string[]> keywordsMap) | ||
{ | ||
this.keywordsMap = keywordsMap.ToImmutableDictionary(x => x.Key.ToLowerInvariant(), x => x.Value, StringComparer.InvariantCultureIgnoreCase); | ||
|
||
// Validate | ||
foreach ((var key, var keywords) in keywordsMap) | ||
{ | ||
if (key.Split('/').Length > 2) | ||
{ | ||
throw new ArgumentException($"Keys in {nameof(keywordsMap)} can have at most one slash: {key}"); | ||
} | ||
} | ||
} | ||
|
||
public string? TryGetResourceTypeFilterText(ResourceTypeReference resourceType) | ||
{ | ||
// Lower-case all resource types in filter text otherwise editor may prefer those with casing that match what the user has already typed (#9168), thus missorting API versions | ||
var filter = resourceType.Type.ToLowerInvariant(); | ||
string[]? keywords; | ||
|
||
// We want to search using the top-level resource type, including subtypes | ||
// Microsoft.web/serverFarms/xxx -> top-level key is Microsoft.web | ||
// Microsoft.web/serverFarms/xxx -> second-level key is Microsoft.web/serverFarms | ||
var indexFirstSlash = filter.IndexOf('/'); | ||
var topLevelKey = indexFirstSlash > 0 ? filter[0..indexFirstSlash] : filter; | ||
if (!keywordsMap.TryGetValue(topLevelKey, out keywords)) | ||
{ | ||
if (indexFirstSlash > 0) | ||
{ | ||
var indexSecondSlash = filter.IndexOf('/', indexFirstSlash + 1); | ||
var secondLevelKey = indexSecondSlash > 0 ? filter[0..indexSecondSlash] : filter; | ||
keywordsMap.TryGetValue(secondLevelKey, out keywords); | ||
} | ||
} | ||
|
||
// The filter text, like the insertText, must include the single quotes that surround the resource type in the resource declaration | ||
return keywords is string[]? | ||
StringUtils.EscapeBicepString($"{string.Join(',', keywords)},{filter}") : | ||
null; // null - let vscode use the default (label) | ||
} | ||
} | ||
} |