Skip to content

Commit 4a6cf80

Browse files
authored
Enhance AVM module completion by adding mock MS Graph extensions and improving readability for long paths
1 parent e0cb5f2 commit 4a6cf80

3 files changed

Lines changed: 142 additions & 1 deletion

File tree

‎src/Bicep.Core.IntegrationTests/ExamplesTests.cs‎

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System.Diagnostics.CodeAnalysis;
5+
using Bicep.Core.Configuration;
56
using Bicep.Core.Diagnostics;
67
using Bicep.Core.Emit;
78
using Bicep.Core.Extensions;
@@ -20,6 +21,10 @@ namespace Bicep.Core.IntegrationTests
2021
[TestClass]
2122
public class ExamplesTests
2223
{
24+
private const string MsGraphSampleExtensionVersion = "0.1.8-preview";
25+
private const string MsGraphBetaRepository = "bicep/extensions/microsoftgraph/beta";
26+
private const string MsGraphV1Repository = "bicep/extensions/microsoftgraph/v1.0";
27+
2328
private static ServiceBuilder Services => new ServiceBuilder().WithDisabledAnalyzersConfiguration();
2429

2530
[NotNull]
@@ -33,7 +38,13 @@ public static async Task RunExampleTest(TestContext testContext, EmbeddedFile em
3338
var bicepFile = baselineFolder.EntryFile;
3439
var jsonFile = baselineFolder.GetFileOrEnsureCheckedIn(Path.ChangeExtension(embeddedBicep.FileName, jsonFileExtension));
3540

36-
var compiler = Services.WithFeatureOverrides(features).Build().GetCompiler();
41+
var services = Services.WithFeatureOverrides(features);
42+
if (RequiresMockMsGraphExtensions(embeddedBicep))
43+
{
44+
services = await AddMockMsGraphExtensions(services);
45+
}
46+
47+
var compiler = services.Build().GetCompiler();
3748
var compilation = await compiler.CreateCompilation(bicepFile.OutputFileUri.ToIOUri());
3849
var model = compilation.GetEntrypointSemanticModel();
3950

@@ -107,6 +118,29 @@ public void ExampleData_should_return_a_number_of_records()
107118
private static IEnumerable<object[]> GetAllExampleData()
108119
=> ExampleData.GetAllExampleData().Select(x => new object[] { x.BicepFile });
109120

121+
private static bool RequiresMockMsGraphExtensions(EmbeddedFile embeddedBicep)
122+
=> embeddedBicep.StreamPath.StartsWith("Files/user_submitted/extensibility/microsoftGraph/", StringComparison.Ordinal);
123+
124+
private static async Task<ServiceBuilder> AddMockMsGraphExtensions(ServiceBuilder services)
125+
{
126+
services = services.WithContainerRegistryClientFactory(RegistryHelper.CreateMockRegistryClient(
127+
new RegistryHelper.RepoDescriptor(LanguageConstants.BicepPublicMcrRegistry, MsGraphBetaRepository, [MsGraphSampleExtensionVersion]),
128+
new RegistryHelper.RepoDescriptor(LanguageConstants.BicepPublicMcrRegistry, MsGraphV1Repository, [MsGraphSampleExtensionVersion])));
129+
130+
var serviceProvider = services.Build();
131+
await RegistryHelper.PublishExtensionToRegistryAsync(
132+
serviceProvider,
133+
$"br:{LanguageConstants.BicepPublicMcrRegistry}/{MsGraphBetaRepository}:{MsGraphSampleExtensionVersion}",
134+
ExtensionResourceTypeHelper.GetMockMsGraphTypesTgz("MicrosoftGraphBeta", MsGraphSampleExtensionVersion, "beta"));
135+
136+
await RegistryHelper.PublishExtensionToRegistryAsync(
137+
serviceProvider,
138+
$"br:{LanguageConstants.BicepPublicMcrRegistry}/{MsGraphV1Repository}:{MsGraphSampleExtensionVersion}",
139+
ExtensionResourceTypeHelper.GetMockMsGraphTypesTgz("MicrosoftGraph", MsGraphSampleExtensionVersion, "v1.0"));
140+
141+
return services;
142+
}
143+
110144
private static bool IsPermittedMissingTypeDiagnostic(IDiagnostic diagnostic)
111145
{
112146
if (diagnostic.Code != "BCP081")

‎src/Bicep.Core.UnitTests/Utils/ExtensionResourceTypeHelper.cs‎

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,112 @@ public static BinaryData GetMockDesiredStateConfigurationTypesTgz()
340340
("types.json", StreamHelper.GetString(stream => TypeSerializer.Serialize(stream, factory.GetTypes()))));
341341
}
342342

343+
public static BinaryData GetMockMsGraphTypesTgz(string extensionName, string extensionVersion, string apiVersion)
344+
{
345+
var factory = new TypeFactory([]);
346+
347+
var stringType = factory.Create(() => new StringType());
348+
var booleanType = factory.Create(() => new BooleanType());
349+
var anyType = factory.Create(() => new AnyType());
350+
var stringArrayType = factory.Create(() => new ArrayType(factory.GetReference(stringType)));
351+
var anyArrayType = factory.Create(() => new ArrayType(factory.GetReference(anyType)));
352+
353+
var stringTypeRef = factory.GetReference(stringType);
354+
var booleanTypeRef = factory.GetReference(booleanType);
355+
var anyTypeRef = factory.GetReference(anyType);
356+
var stringArrayTypeRef = factory.GetReference(stringArrayType);
357+
var anyArrayTypeRef = factory.GetReference(anyArrayType);
358+
359+
ObjectTypeProperty Property(ITypeReference typeRef, ObjectTypePropertyFlags flags = ObjectTypePropertyFlags.None) => new(typeRef, flags, null);
360+
361+
ResourceType Resource(string name, Dictionary<string, ObjectTypeProperty> properties)
362+
{
363+
var bodyType = factory.Create(() => new ObjectType(name, properties, null));
364+
365+
return factory.Create(() => new ResourceType(
366+
name,
367+
factory.GetReference(bodyType),
368+
null,
369+
writableScopes_in: ScopeType.All,
370+
readableScopes_in: ScopeType.All));
371+
}
372+
373+
Dictionary<string, ObjectTypeProperty> ApplicationProperties() => new()
374+
{
375+
["uniqueName"] = Property(stringTypeRef, ObjectTypePropertyFlags.Required),
376+
["displayName"] = Property(stringTypeRef),
377+
["appId"] = Property(stringTypeRef, ObjectTypePropertyFlags.ReadOnly),
378+
["id"] = Property(stringTypeRef, ObjectTypePropertyFlags.ReadOnly),
379+
["appRoles"] = Property(anyArrayTypeRef),
380+
["api"] = Property(anyTypeRef),
381+
};
382+
383+
ResourceType[] resourceTypes = apiVersion switch
384+
{
385+
"beta" =>
386+
[
387+
Resource("Microsoft.Graph/applications@beta", ApplicationProperties()),
388+
Resource("Microsoft.Graph/servicePrincipals@beta", new()
389+
{
390+
["appId"] = Property(stringTypeRef, ObjectTypePropertyFlags.Required),
391+
["id"] = Property(stringTypeRef, ObjectTypePropertyFlags.ReadOnly),
392+
}),
393+
Resource("Microsoft.Graph/oauth2PermissionGrants@beta", new()
394+
{
395+
["clientId"] = Property(stringTypeRef),
396+
["consentType"] = Property(stringTypeRef),
397+
["resourceId"] = Property(stringTypeRef),
398+
["scope"] = Property(stringTypeRef),
399+
["id"] = Property(stringTypeRef, ObjectTypePropertyFlags.ReadOnly),
400+
}),
401+
Resource("Microsoft.Graph/appRoleAssignedTo@beta", new()
402+
{
403+
["appRoleId"] = Property(stringTypeRef),
404+
["principalId"] = Property(stringTypeRef),
405+
["resourceId"] = Property(stringTypeRef),
406+
["id"] = Property(stringTypeRef, ObjectTypePropertyFlags.ReadOnly),
407+
}),
408+
Resource("Microsoft.Graph/groups@beta", new()
409+
{
410+
["uniqueName"] = Property(stringTypeRef, ObjectTypePropertyFlags.Required),
411+
["displayName"] = Property(stringTypeRef),
412+
["mailEnabled"] = Property(booleanTypeRef),
413+
["mailNickname"] = Property(stringTypeRef),
414+
["securityEnabled"] = Property(booleanTypeRef),
415+
["groupTypes"] = Property(stringArrayTypeRef),
416+
["owners"] = Property(stringArrayTypeRef),
417+
["id"] = Property(stringTypeRef, ObjectTypePropertyFlags.ReadOnly),
418+
}),
419+
],
420+
"v1.0" =>
421+
[
422+
Resource("Microsoft.Graph/applications@v1.0", ApplicationProperties()),
423+
Resource("Microsoft.Graph/applications/federatedIdentityCredentials@v1.0", new()
424+
{
425+
["name"] = Property(stringTypeRef, ObjectTypePropertyFlags.Required),
426+
["audiences"] = Property(stringArrayTypeRef),
427+
["description"] = Property(stringTypeRef),
428+
["issuer"] = Property(stringTypeRef),
429+
["subject"] = Property(stringTypeRef),
430+
["id"] = Property(stringTypeRef, ObjectTypePropertyFlags.ReadOnly),
431+
}),
432+
],
433+
_ => throw new ArgumentException($"Unsupported Microsoft Graph API version '{apiVersion}'.", nameof(apiVersion)),
434+
};
435+
436+
var settings = new TypeSettings(name: extensionName, version: extensionVersion, isSingleton: false, configurationType: null!);
437+
var index = new TypeIndex(
438+
resourceTypes.ToDictionary(x => x.Name, x => new CrossFileTypeReference("types.json", factory.GetIndex(x))),
439+
new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<CrossFileTypeReference>>>(),
440+
[],
441+
settings,
442+
null);
443+
444+
return GetTypesTgzBytesFromFiles(
445+
("index.json", StreamHelper.GetString(stream => TypeSerializer.SerializeIndex(stream, index))),
446+
("types.json", StreamHelper.GetString(stream => TypeSerializer.Serialize(stream, factory.GetTypes()))));
447+
}
448+
343449
public static BinaryData GetTypesTgzBytesFromFiles(params (string filePath, string contents)[] files)
344450
{
345451
var stream = new MemoryStream();

‎src/Bicep.LangServer.UnitTests/Completions/ModuleReferenceCompletionProviderTests.cs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ public async Task GetFilteredCompletions_WithPublicAvmModulePathCompletions_Uses
592592
catalog,
593593
settingsProvider,
594594
BicepTestConstants.CreateMockTelemetryProvider().Object,
595+
BicepTestConstants.TestRegistryConfiguration,
595596
avmDisplayNameProviderMock.Object);
596597
var completions = await GetAndResolveCompletionItems(sourceFile, completionContext, moduleReferenceCompletionProvider);
597598

0 commit comments

Comments
 (0)