From 09afb76cbe4fab459f41713de3e30dc7a8c625b7 Mon Sep 17 00:00:00 2001 From: Anthony Martin <38542602+anthony-c-martin@users.noreply.github.com> Date: Wed, 6 Mar 2024 23:05:29 -0500 Subject: [PATCH 1/2] Correct code fix logic for legacy provider --- .../ExtensibilityTests.cs | 27 +++++++++++++++++ ...ConfigurationManagedProviderDeclaration.cs | 11 ------- .../Providers/IProviderSpecification.cs | 29 +++++++++++++++++++ .../Providers/InlinedProviderSpecification.cs | 13 --------- .../Providers/LegacyProviderSpecification.cs | 8 ----- .../Providers/ProviderSpecificationFactory.cs | 5 ++-- .../Providers/ProviderSpecificationTrivia.cs | 12 -------- 7 files changed, 58 insertions(+), 47 deletions(-) delete mode 100644 src/Bicep.Core/TypeSystem/Providers/ConfigurationManagedProviderDeclaration.cs delete mode 100644 src/Bicep.Core/TypeSystem/Providers/InlinedProviderSpecification.cs delete mode 100644 src/Bicep.Core/TypeSystem/Providers/LegacyProviderSpecification.cs delete mode 100644 src/Bicep.Core/TypeSystem/Providers/ProviderSpecificationTrivia.cs diff --git a/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs b/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs index 79fd1ed0ab6..2dd44ca8749 100644 --- a/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs +++ b/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using Bicep.Core.CodeAction; using Bicep.Core.Diagnostics; using Bicep.Core.IntegrationTests.Extensibility; using Bicep.Core.UnitTests; @@ -460,6 +461,32 @@ public void Child_resource_with_parent_namespace_mismatch_returns_error() }); } + [TestMethod] + public void LegacyProvider_codefix_works() + { + var originalFile = @" +provider 'bar@0.0.1' with { + connectionString: 'asdf' +} as stg +"; + + var result = CompilationHelper.Compile(Services, originalFile); + + result.Should().HaveDiagnostics(new[] { + ("BCP395", DiagnosticLevel.Warning, "Declaring provider namespaces using the '@' expression has been deprecated. Please use an identifier instead."), + }); + + var diagnostic = result.Diagnostics.OfType().Single(); + var fix = diagnostic.Fixes.Single(); + + fix.Kind.Should().Be(CodeFixKind.QuickFix); + fix.Should().HaveResult(originalFile, @" +provider bar with { + connectionString: 'asdf' +} as stg +"); + } + [TestMethod] public void Bar_import_end_to_end_test() { diff --git a/src/Bicep.Core/TypeSystem/Providers/ConfigurationManagedProviderDeclaration.cs b/src/Bicep.Core/TypeSystem/Providers/ConfigurationManagedProviderDeclaration.cs deleted file mode 100644 index f65463ea145..00000000000 --- a/src/Bicep.Core/TypeSystem/Providers/ConfigurationManagedProviderDeclaration.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using Bicep.Core.Parsing; - -namespace Bicep.Core.TypeSystem.Providers; - -public record ConfigurationManagedProviderSpecification(string NamespaceIdentifier, bool IsValid, TextSpan Span) : IProviderSpecification -{ - public string? Version => null; -}; diff --git a/src/Bicep.Core/TypeSystem/Providers/IProviderSpecification.cs b/src/Bicep.Core/TypeSystem/Providers/IProviderSpecification.cs index 3b9f5f3f336..bd635a550d1 100644 --- a/src/Bicep.Core/TypeSystem/Providers/IProviderSpecification.cs +++ b/src/Bicep.Core/TypeSystem/Providers/IProviderSpecification.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using Bicep.Core.Parsing; using Bicep.Core.Syntax; namespace Bicep.Core.TypeSystem.Providers; @@ -10,3 +11,31 @@ public interface IProviderSpecification : ISymbolNameSource string NamespaceIdentifier { get; } string? Version { get; } } + +public record LegacyProviderSpecification( + string NamespaceIdentifier, + string Version, + bool IsValid, + TextSpan Span) : IProviderSpecification; + +public record InlinedProviderSpecification( + string NamespaceIdentifier, + string Version, + string UnexpandedArtifactAddress, + bool IsValid, + TextSpan Span) : IProviderSpecification; + +public record ConfigurationManagedProviderSpecification( + string NamespaceIdentifier, + bool IsValid, + TextSpan Span) : IProviderSpecification +{ + public string? Version => null; +} + +public record ProviderSpecificationTrivia(TextSpan Span) : IProviderSpecification +{ + public string NamespaceIdentifier => LanguageConstants.ErrorName; + public bool IsValid => false; + public string? Version => null; +} \ No newline at end of file diff --git a/src/Bicep.Core/TypeSystem/Providers/InlinedProviderSpecification.cs b/src/Bicep.Core/TypeSystem/Providers/InlinedProviderSpecification.cs deleted file mode 100644 index 05c991a73c4..00000000000 --- a/src/Bicep.Core/TypeSystem/Providers/InlinedProviderSpecification.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using Bicep.Core.Parsing; - -namespace Bicep.Core.TypeSystem.Providers; - -public record InlinedProviderSpecification( - string NamespaceIdentifier, - string Version, - string UnexpandedArtifactAddress, - bool IsValid, - TextSpan Span) : IProviderSpecification; diff --git a/src/Bicep.Core/TypeSystem/Providers/LegacyProviderSpecification.cs b/src/Bicep.Core/TypeSystem/Providers/LegacyProviderSpecification.cs deleted file mode 100644 index 08e0d511d0f..00000000000 --- a/src/Bicep.Core/TypeSystem/Providers/LegacyProviderSpecification.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using Bicep.Core.Parsing; - -namespace Bicep.Core.TypeSystem.Providers; - -public record LegacyProviderSpecification(string NamespaceIdentifier, string Version, bool IsValid, TextSpan Span) : IProviderSpecification; diff --git a/src/Bicep.Core/TypeSystem/Providers/ProviderSpecificationFactory.cs b/src/Bicep.Core/TypeSystem/Providers/ProviderSpecificationFactory.cs index 23e5be6e6e6..6653e5065d6 100644 --- a/src/Bicep.Core/TypeSystem/Providers/ProviderSpecificationFactory.cs +++ b/src/Bicep.Core/TypeSystem/Providers/ProviderSpecificationFactory.cs @@ -44,7 +44,7 @@ public static IProviderSpecification CreateProviderSpecification(SyntaxBase synt legacyMatch.Groups["name"].Value, legacyMatch.Groups["version"].Value, IsValid: true, - stringSyntax.GetInnerSpan()); + stringSyntax.Span); } var registryMatch = InlinedSpecificationPattern().Match(value); @@ -57,12 +57,11 @@ public static IProviderSpecification CreateProviderSpecification(SyntaxBase synt var address = registryMatch.Groups["address"].Value; var version = registryMatch.Groups["version"].Value; - var span = stringSyntax.GetInnerSpan(); // We normalize the artifact address to the way we represent module addresses, see https://github.com/Azure/bicep/issues/12202 var unexpandedArtifactAddress = $"{address}:{version}"; var name = RepositoryNamePattern().Match(address).Groups["name"].Value; - return new InlinedProviderSpecification(name, version, unexpandedArtifactAddress, IsValid: true, span); + return new InlinedProviderSpecification(name, version, unexpandedArtifactAddress, IsValid: true, stringSyntax.Span); } } diff --git a/src/Bicep.Core/TypeSystem/Providers/ProviderSpecificationTrivia.cs b/src/Bicep.Core/TypeSystem/Providers/ProviderSpecificationTrivia.cs deleted file mode 100644 index c433d2e4b54..00000000000 --- a/src/Bicep.Core/TypeSystem/Providers/ProviderSpecificationTrivia.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using Bicep.Core.Parsing; - -namespace Bicep.Core.TypeSystem.Providers; -public record ProviderSpecificationTrivia(TextSpan Span) : IProviderSpecification -{ - public string NamespaceIdentifier => LanguageConstants.ErrorName; - public bool IsValid => false; - public string? Version => null; -}; From f8872c25da531eb6b0e72854f914e696d84503a1 Mon Sep 17 00:00:00 2001 From: Anthony Martin <38542602+anthony-c-martin@users.noreply.github.com> Date: Wed, 6 Mar 2024 23:56:10 -0500 Subject: [PATCH 2/2] Correct other minor bugs relating to new provider syntax --- .../ExamplesTests.cs | 2 +- .../ExtensibilityTests.cs | 96 ++++++++++--------- .../OutputsTests.cs | 14 ++- .../ParametersTests.cs | 14 ++- .../ProviderImportTests.cs | 73 +++++++------- .../ScenarioTests.cs | 4 +- .../aks/modules/kubernetes.bicep | 2 +- .../extensibility/microsoftGraph/main.bicep | 2 +- .../microsoftGraph/main.existing.bicep | 2 +- .../UseRecentApiVersionRuleTests.cs | 2 +- .../CompletionTests.cs | 18 ++-- .../manifest.bicep | 2 +- .../wordpress/manifest.bicep | 2 +- .../BicepCompletionProviderTests.cs | 9 +- .../Completions/BicepCompletionContext.cs | 16 ++-- .../Completions/BicepCompletionProvider.cs | 3 +- .../Handlers/BicepHoverHandler.cs | 3 +- .../ImportKubernetesManifestHandler.cs | 2 +- 18 files changed, 147 insertions(+), 119 deletions(-) diff --git a/src/Bicep.Core.IntegrationTests/ExamplesTests.cs b/src/Bicep.Core.IntegrationTests/ExamplesTests.cs index 50790a42552..e8ac3e1aba5 100644 --- a/src/Bicep.Core.IntegrationTests/ExamplesTests.cs +++ b/src/Bicep.Core.IntegrationTests/ExamplesTests.cs @@ -39,7 +39,7 @@ private async Task RunExampleTest(EmbeddedFile embeddedBicep, FeatureProviderOve { DiagnosticAssertions.DoWithDiagnosticAnnotations( file, - diagnostics.Where(d => !IsPermittedMissingTypeDiagnostic(d)).Where(d => !d.Code.Equals("BCP395")), + diagnostics.Where(d => !IsPermittedMissingTypeDiagnostic(d)), diagnostics => { diagnostics.Should().BeEmpty("{0} should not have warnings or errors", file.FileUri.LocalPath); diff --git a/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs b/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs index 2dd44ca8749..0217089d8d5 100644 --- a/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs +++ b/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using Bicep.Core.CodeAction; +using Bicep.Core.Configuration; using Bicep.Core.Diagnostics; using Bicep.Core.IntegrationTests.Extensibility; using Bicep.Core.UnitTests; @@ -18,17 +19,26 @@ public class ExtensibilityTests : TestBase { private ServiceBuilder Services => new ServiceBuilder() .WithFeatureOverrides(new(ExtensibilityEnabled: true)) + .WithConfigurationPatch(c => c.WithProvidersConfiguration(""" + { + "az": "builtin:", + "kubernetes": "builtin:", + "microsoftGraph": "builtin:", + "foo": "builtin:", + "bar": "builtin:" + } + """)) .WithNamespaceProvider(new TestExtensibilityNamespaceProvider(BicepTestConstants.ResourceTypeProviderFactory)); [TestMethod] public void Bar_import_bad_config_is_blocked() { var result = CompilationHelper.Compile(Services, @" -provider 'bar@0.0.1' with { +provider bar with { madeUpProperty: 'asdf' } as stg "); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { ("BCP035", DiagnosticLevel.Error, "The specified \"object\" declaration is missing the following required properties: \"connectionString\"."), ("BCP037", DiagnosticLevel.Error, "The property \"madeUpProperty\" is not allowed on objects of type \"configuration\". Permissible properties include \"connectionString\".") }); @@ -38,22 +48,22 @@ public void Bar_import_bad_config_is_blocked() public void Bar_import_can_be_duplicated() { var result = CompilationHelper.Compile(Services, """ - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'connectionString1' } as stg - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'connectionString2' } as stg2 """); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); } [TestMethod] public void Bar_import_basic_test() { var result = CompilationHelper.Compile(Services, """ - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'asdf' } as stg @@ -67,18 +77,18 @@ public void Bar_import_basic_test() base64Content: base64('sadfasdfd') } """); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); } [TestMethod] public void Ambiguous_type_references_return_errors() { var result = CompilationHelper.Compile(Services, """ - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'asdf' } as stg - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'asdf' } as stg2 @@ -86,16 +96,16 @@ public void Ambiguous_type_references_return_errors() name: 'myblob' } """); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { ("BCP264", DiagnosticLevel.Error, "Resource type \"container\" is declared in multiple imported namespaces (\"stg\", \"stg2\"), and must be fully-qualified."), }); result = CompilationHelper.Compile(Services, """ - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'asdf' } as stg - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'asdf' } as stg2 @@ -103,14 +113,14 @@ public void Ambiguous_type_references_return_errors() name: 'myblob' } """); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); } [TestMethod] public void Bar_import_basic_test_loops_and_referencing() { var result = CompilationHelper.Compile(Services, """ - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'asdf' } as stg @@ -138,7 +148,7 @@ public void Bar_import_basic_test_loops_and_referencing() #disable-next-line prefer-unquoted-property-names output base64Content string = blobs[3]['base64Content'] """); - result.ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.Should().NotHaveAnyDiagnostics(); result.Template.Should().HaveValueAtPath("$.outputs['sourceContainerName'].value", "[reference('container').name]"); result.Template.Should().HaveValueAtPath("$.outputs['sourceContainerNameSquare'].value", "[reference('container').name]"); result.Template.Should().HaveValueAtPath("$.outputs['miscBlobContainerName'].value", "[reference(format('blobs[{0}]', mod(13, 10))).containerName]"); @@ -150,7 +160,7 @@ public void Bar_import_basic_test_loops_and_referencing() public void Foo_import_basic_test_loops_and_referencing() { var result = CompilationHelper.Compile(Services, """ - provider 'foo@1.2.3' as foo + provider foo as foo param numApps int resource myApp 'application' = { @@ -168,7 +178,7 @@ public void Foo_import_basic_test_loops_and_referencing() #disable-next-line prefer-unquoted-property-names output myAppsLoopId2 string = myAppsLoop[3]['appId'] """); - result.ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.Should().NotHaveAnyDiagnostics(); result.Template.Should().HaveValueAtPath("$.outputs['myAppId'].value", "[reference('myApp').appId]"); result.Template.Should().HaveValueAtPath("$.outputs['myAppId2'].value", "[reference('myApp').appId]"); result.Template.Should().HaveValueAtPath("$.outputs['myAppsLoopId'].value", "[reference(format('myAppsLoop[{0}]', mod(13, parameters('numApps')))).appId]"); @@ -180,7 +190,7 @@ public void Foo_import_existing_requires_uniqueName() { // we've accidentally used 'name' even though this resource type doesn't support it var result = CompilationHelper.Compile(Services, """ - provider 'foo@1.2.3' + provider foo resource myApp 'application' existing = { name: 'foo' @@ -188,7 +198,7 @@ public void Foo_import_existing_requires_uniqueName() """); result.Should().NotGenerateATemplate(); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP035", DiagnosticLevel.Error, "The specified \"resource\" declaration is missing the following required properties: \"uniqueName\"."), ("no-unused-existing-resources", DiagnosticLevel.Warning, "Existing resource \"myApp\" is declared but never used."), ("BCP037", DiagnosticLevel.Error, "The property \"name\" is not allowed on objects of type \"application\". Permissible properties include \"uniqueName\". If this is an inaccuracy in the documentation, please report it to the Bicep Team."), @@ -196,7 +206,7 @@ public void Foo_import_existing_requires_uniqueName() // oops! let's change it to 'uniqueName' result = CompilationHelper.Compile(Services, """ - provider 'foo@1.2.3' as foo + provider foo as foo resource myApp 'application' existing = { uniqueName: 'foo' @@ -204,7 +214,7 @@ public void Foo_import_existing_requires_uniqueName() """); result.Should().GenerateATemplate(); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("no-unused-existing-resources", DiagnosticLevel.Warning, "Existing resource \"myApp\" is declared but never used."), }); } @@ -213,7 +223,7 @@ public void Foo_import_existing_requires_uniqueName() public void Kubernetes_import_existing_warns_with_readonly_fields() { var result = CompilationHelper.Compile(Services, """ - provider 'kubernetes@1.0.0' with { + provider kubernetes with { namespace: 'default' kubeConfig: '' } @@ -232,7 +242,7 @@ public void Kubernetes_import_existing_warns_with_readonly_fields() """); result.Should().GenerateATemplate(); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("no-unused-existing-resources", DiagnosticLevel.Warning, "Existing resource \"service\" is declared but never used."), ("BCP073", DiagnosticLevel.Warning, "The property \"labels\" is read-only. Expressions cannot be assigned to read-only properties. If this is an inaccuracy in the documentation, please report it to the Bicep Team."), ("BCP073", DiagnosticLevel.Warning, "The property \"annotations\" is read-only. Expressions cannot be assigned to read-only properties. If this is an inaccuracy in the documentation, please report it to the Bicep Team."), @@ -243,19 +253,19 @@ public void Kubernetes_import_existing_warns_with_readonly_fields() public void Kubernetes_competing_imports_are_blocked() { var result = CompilationHelper.Compile(Services, @" -provider 'kubernetes@1.0.0' with { +provider kubernetes with { namespace: 'default' kubeConfig: '' } -provider 'kubernetes@1.0.0' with { +provider kubernetes with { namespace: 'default' kubeConfig: '' } "); result.Should().NotGenerateATemplate(); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP028", DiagnosticLevel.Error, "Identifier \"kubernetes\" is declared multiple times. Remove or rename the duplicates."), ("BCP207", DiagnosticLevel.Error, "Namespace \"kubernetes\" is declared multiple times. Remove the duplicates."), ("BCP028", DiagnosticLevel.Error, "Identifier \"kubernetes\" is declared multiple times. Remove or rename the duplicates."), @@ -267,7 +277,7 @@ public void Kubernetes_competing_imports_are_blocked() public void Kubernetes_import_existing_resources() { var result = CompilationHelper.Compile(Services, @" -provider 'kubernetes@1.0.0' with { +provider kubernetes with { namespace: 'default' kubeConfig: '' } @@ -292,7 +302,7 @@ public void Kubernetes_import_existing_resources() "); result.Should().GenerateATemplate(); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("no-unused-existing-resources", DiagnosticLevel.Warning, "Existing resource \"service\" is declared but never used."), ("no-unused-existing-resources", DiagnosticLevel.Warning, "Existing resource \"secret\" is declared but never used."), ("no-unused-existing-resources", DiagnosticLevel.Warning, "Existing resource \"configmap\" is declared but never used."), @@ -303,7 +313,7 @@ public void Kubernetes_import_existing_resources() public void Kubernetes_import_existing_connectionstring_test() { var result = CompilationHelper.Compile(Services, @" -provider 'kubernetes@1.0.0' with { +provider kubernetes with { namespace: 'default' kubeConfig: '' } @@ -334,14 +344,14 @@ public void Kubernetes_import_existing_connectionstring_test() "); result.Should().GenerateATemplate(); - result.ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.Should().NotHaveAnyDiagnostics(); } [TestMethod] public void Kubernetes_CustomResourceType_EmitWarning() { var result = CompilationHelper.Compile(Services, """ - provider 'kubernetes@1.0.0' with { + provider kubernetes with { namespace: 'default' kubeConfig: '' } @@ -353,7 +363,7 @@ public void Kubernetes_CustomResourceType_EmitWarning() """); result.Should().GenerateATemplate(); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP081", DiagnosticLevel.Warning, @"Resource type ""custom/Foo@v1"" does not have types available."), }); } @@ -362,7 +372,7 @@ public void Kubernetes_CustomResourceType_EmitWarning() public void Kubernetes_AmbiguousFallbackType_MustFullyQualify() { var result = CompilationHelper.Compile(Services, """ - provider 'kubernetes@1.0.0' with { + provider kubernetes with { namespace: 'default' kubeConfig: '' } @@ -384,7 +394,7 @@ public void Kubernetes_AmbiguousFallbackType_MustFullyQualify() """); result.Should().NotGenerateATemplate(); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP264", DiagnosticLevel.Error, @"Resource type ""Microsoft.Compute/availabilitySets@2023-01-01"" is declared in multiple imported namespaces (""az"", ""kubernetes""), and must be fully-qualified."), ("BCP035", DiagnosticLevel.Error, @"The specified ""resource"" declaration is missing the following required properties: ""name""."), ("BCP081", DiagnosticLevel.Warning, @"Resource type ""Microsoft.Compute/availabilitySets@2023-01-01"" does not have types available."), @@ -396,7 +406,7 @@ public void Kubernetes_AmbiguousFallbackType_MustFullyQualify() public void Bar_import_basic_test_with_qualified_type() { var result = CompilationHelper.Compile(Services, """ - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'asdf' } as stg @@ -410,14 +420,14 @@ public void Bar_import_basic_test_with_qualified_type() base64Content: base64('sadfasdfd') } """); - result.ExcludingDiagnostics("BCP395").ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); } [TestMethod] public void Invalid_namespace_qualifier_returns_error() { var result = CompilationHelper.Compile(Services, """ - provider 'bar@0.0.1' with { + provider bar with { connectionString: 'asdf' } as stg @@ -432,7 +442,7 @@ public void Invalid_namespace_qualifier_returns_error() } """); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { ("BCP208", DiagnosticLevel.Error, "The specified namespace \"foo\" is not recognized. Specify a resource reference using one of the following namespaces: \"az\", \"stg\", \"sys\"."), ("BCP208", DiagnosticLevel.Error, "The specified namespace \"bar\" is not recognized. Specify a resource reference using one of the following namespaces: \"az\", \"stg\", \"sys\"."), }); @@ -442,7 +452,7 @@ public void Invalid_namespace_qualifier_returns_error() public void Child_resource_with_parent_namespace_mismatch_returns_error() { var result = CompilationHelper.Compile(Services, @" -provider 'bar@0.0.1' with { +provider bar with { connectionString: 'asdf' } as stg @@ -455,7 +465,7 @@ public void Child_resource_with_parent_namespace_mismatch_returns_error() } "); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { ("BCP081", DiagnosticLevel.Warning, "Resource type \"Microsoft.Storage/storageAccounts@2020-01-01\" does not have types available."), ("BCP210", DiagnosticLevel.Error, "Resource type belonging to namespace \"stg\" cannot have a parent resource type belonging to different namespace \"az\"."), }); @@ -465,7 +475,7 @@ public void Child_resource_with_parent_namespace_mismatch_returns_error() public void LegacyProvider_codefix_works() { var originalFile = @" -provider 'bar@0.0.1' with { +provider 'bar@1.0.0' with { connectionString: 'asdf' } as stg "; @@ -516,7 +526,7 @@ public void Bar_import_end_to_end_test() @secure() param connectionString string -provider 'bar@0.0.1' with { +provider bar with { connectionString: connectionString } as stg @@ -533,7 +543,7 @@ public void Bar_import_end_to_end_test() ("blob.txt", @" Hello from Bicep!")); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); result.Template.Should().DeepEqual(JToken.Parse(""" { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", diff --git a/src/Bicep.Core.IntegrationTests/OutputsTests.cs b/src/Bicep.Core.IntegrationTests/OutputsTests.cs index f83c365e8c3..7ed623ad35a 100644 --- a/src/Bicep.Core.IntegrationTests/OutputsTests.cs +++ b/src/Bicep.Core.IntegrationTests/OutputsTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System.Diagnostics.CodeAnalysis; +using Bicep.Core.Configuration; using Bicep.Core.Diagnostics; using Bicep.Core.IntegrationTests.Extensibility; using Bicep.Core.TypeSystem.Types; @@ -25,6 +26,15 @@ public class OutputsTests private ServiceBuilder ServicesWithExtensibility => new ServiceBuilder() .WithFeatureOverrides(new(TestContext, ExtensibilityEnabled: true, ResourceTypedParamsAndOutputsEnabled: true)) + .WithConfigurationPatch(c => c.WithProvidersConfiguration(""" + { + "az": "builtin:", + "kubernetes": "builtin:", + "microsoftGraph": "builtin:", + "foo": "builtin:", + "bar": "builtin:" + } + """)) .WithNamespaceProvider(new TestExtensibilityNamespaceProvider(BicepTestConstants.ResourceTypeProviderFactory)); [TestMethod] @@ -225,7 +235,7 @@ public void Output_cannot_use_extensibility_resource_type() { var result = CompilationHelper.Compile(ServicesWithExtensibility, """ - provider 'bar@1.0.0' with { + provider bar with { connectionString: 'asdf' } as stg @@ -236,7 +246,7 @@ public void Output_cannot_use_extensibility_resource_type() output out resource = container """); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { ("BCP227", DiagnosticLevel.Error, "The type \"container\" cannot be used as a parameter or output type. Extensibility types are currently not supported as parameters or outputs."), }); diff --git a/src/Bicep.Core.IntegrationTests/ParametersTests.cs b/src/Bicep.Core.IntegrationTests/ParametersTests.cs index 3330a6ddaa2..051481a5f8a 100644 --- a/src/Bicep.Core.IntegrationTests/ParametersTests.cs +++ b/src/Bicep.Core.IntegrationTests/ParametersTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System.Diagnostics.CodeAnalysis; +using Bicep.Core.Configuration; using Bicep.Core.Diagnostics; using Bicep.Core.IntegrationTests.Extensibility; using Bicep.Core.Syntax; @@ -24,6 +25,15 @@ public class ParameterTests private ServiceBuilder ServicesWithExtensibility => new ServiceBuilder() .WithFeatureOverrides(new(TestContext, ExtensibilityEnabled: true, ResourceTypedParamsAndOutputsEnabled: true)) + .WithConfigurationPatch(c => c.WithProvidersConfiguration(""" + { + "az": "builtin:", + "kubernetes": "builtin:", + "microsoftGraph": "builtin:", + "foo": "builtin:", + "bar": "builtin:" + } + """)) .WithNamespaceProvider(new TestExtensibilityNamespaceProvider(BicepTestConstants.ResourceTypeProviderFactory)); [TestMethod] @@ -167,14 +177,14 @@ public void Parameter_can_have_warnings_for_missing_type() public void Parameter_cannot_use_extensibility_resource_type() { var result = CompilationHelper.Compile(ServicesWithExtensibility, """ - provider 'bar@1.0.0' with { + provider bar with { connectionString: 'asdf' } as stg param container resource 'stg:container' output name string = container.name // silence unused params warning """); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { ("BCP227", DiagnosticLevel.Error, "The type \"container\" cannot be used as a parameter or output type. Extensibility types are currently not supported as parameters or outputs."), ("BCP062", DiagnosticLevel.Error, "The referenced declaration with name \"container\" is not valid."), diff --git a/src/Bicep.Core.IntegrationTests/ProviderImportTests.cs b/src/Bicep.Core.IntegrationTests/ProviderImportTests.cs index 08a1d936ace..717764e9425 100644 --- a/src/Bicep.Core.IntegrationTests/ProviderImportTests.cs +++ b/src/Bicep.Core.IntegrationTests/ProviderImportTests.cs @@ -72,13 +72,13 @@ public ResultWithDiagnostic TryGetNamespace(ResourceTypesProvider } [TestMethod] - public async Task Imports_are_disabled_unless_feature_is_enabled() + public async Task Providers_are_disabled_unless_feature_is_enabled() { var services = new ServiceBuilder(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider 'az@1.0.0' + provider az """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP203", DiagnosticLevel.Error, "Using provider statements requires enabling EXPERIMENTAL feature \"Extensibility\"."), // BCP084 is raised because BCP203 prevented the compiler from binding a namespace to the `az` symbol (an ErrorType was bound instead). ("BCP084", DiagnosticLevel.Error, "The symbolic name \"az\" is reserved. Please use a different symbolic name. Reserved namespaces are \"az\", \"sys\"."), @@ -106,9 +106,9 @@ public async Task Provider_Statement_With_Invalid_Keyword_Should_Emit_Diagnostic { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider 'sys@1.0.0' blahblah + provider sys blahblah """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP305", DiagnosticLevel.Error, "Expected the \"with\" keyword, \"as\" keyword, or a new line character at this location."), }); } @@ -118,9 +118,9 @@ public async Task Provider_Statement_Without_Brace_Should_Raise_Error() { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider 'kubernetes@1.0.0' with + provider kubernetes with """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP018", DiagnosticLevel.Error, "Expected the \"{\" character at this location."), }); } @@ -130,12 +130,12 @@ public async Task Provider_Statement_Without_As_Keyword_Should_Raise_Error() { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider 'kubernetes@1.0.0' with { + provider kubernetes with { kubeConfig: 'foo' namespace: 'bar' } something """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP012", DiagnosticLevel.Error, "Expected the \"as\" keyword at this location."), }); } @@ -145,12 +145,12 @@ public async Task Provider_Statement_Without_Alias_Name_Should_Raise_Error() { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider 'kubernetes@1.0.0' with { + provider kubernetes with { kubeConfig: 'foo' namespace: 'bar' } as """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP202", DiagnosticLevel.Error, "Expected a provider alias name at this location."), }); } @@ -160,9 +160,9 @@ public async Task Provider_Statement_Without_Alias_Name_For_Sys_Should_Raise_Err { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider 'sys@1.0.0' as + provider sys as """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP202", DiagnosticLevel.Error, "Expected a provider alias name at this location."), }); } @@ -173,18 +173,17 @@ public async Task Using_import_instead_of_provider_raises_warning() var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ import 'az@1.0.0' as foo """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP381", DiagnosticLevel.Warning, "Declaring provider namespaces with the \"import\" keyword has been deprecated. Please use the \"provider\" keyword instead."), + ("BCP395", DiagnosticLevel.Warning, "Declaring provider namespaces using the '@' expression has been deprecated. Please use an identifier instead."), }); } - [DataRow("az")] - [DataRow("sys")] [TestMethod] - public async Task Using_legacy_import_syntax_raises_warning_for_az_provider(string providerName) + public async Task Using_legacy_import_syntax_raises_warning_for_az_provider() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), $""" - provider '{providerName}@1.0.0' as {providerName} + provider 'az@1.0.0' as az """); result.Should().HaveDiagnostics(new[] { @@ -196,11 +195,11 @@ public async Task Using_legacy_import_syntax_raises_warning_for_az_provider(stri public async Task Import_configuration_is_blocked_by_default() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider 'az@1.0.0' with { + provider az with { foo: 'bar' } """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP205", DiagnosticLevel.Error, "Provider namespace \"az\" does not support configuration."), }); } @@ -220,7 +219,7 @@ public async Task Imports_return_error_with_unrecognized_namespace() public async Task Using_import_statements_frees_up_the_namespace_symbol() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider 'az@1.0.0' as newAz + provider az as newAz var az = 'Fake AZ!' var myRg = newAz.resourceGroup() @@ -229,15 +228,15 @@ public async Task Using_import_statements_frees_up_the_namespace_symbol() output rgLocation string = myRg.location """); - result.ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.Should().NotHaveAnyDiagnostics(); } [TestMethod] public async Task You_can_swap_imported_namespaces_if_you_really_really_want_to() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider 'az@1.0.0' as sys - provider 'sys@1.0.0' as az + provider az as sys + provider sys as az var myRg = sys.resourceGroup() @@ -246,7 +245,7 @@ public async Task You_can_swap_imported_namespaces_if_you_really_really_want_to( """); result.Should().GenerateATemplate(); - result.ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.Should().NotHaveAnyDiagnostics(); result.Template.Should().HaveValueAtPath("$.outputs.rgLocation.metadata.description", "why on earth would you do this?"); } @@ -254,7 +253,7 @@ public async Task You_can_swap_imported_namespaces_if_you_really_really_want_to( public async Task Overwriting_single_built_in_namespace_with_import_is_prohibited() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider 'az@1.0.0' as sys + provider az as sys var myRg = sys.resourceGroup() @@ -268,14 +267,14 @@ public async Task Overwriting_single_built_in_namespace_with_import_is_prohibite public async Task Singleton_imports_cannot_be_used_multiple_times() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider 'az@1.0.0' as az1 - provider 'az@1.0.0' as az2 + provider az as az1 + provider az as az2 - provider 'sys@1.0.0' as sys1 - provider 'sys@1.0.0' as sys2 + provider sys as sys1 + provider sys as sys2 """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP207", DiagnosticLevel.Error, "Namespace \"az\" is declared multiple times. Remove the duplicates."), ("BCP207", DiagnosticLevel.Error, "Namespace \"az\" is declared multiple times. Remove the duplicates."), ("BCP207", DiagnosticLevel.Error, "Namespace \"sys\" is declared multiple times. Remove the duplicates."), @@ -287,14 +286,14 @@ public async Task Singleton_imports_cannot_be_used_multiple_times() public async Task Import_names_must_not_conflict_with_other_symbols() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider 'az@1.0.0' - provider 'kubernetes@1.0.0' with { + provider az + provider kubernetes with { kubeConfig: '' namespace: '' } as az """); - result.ExcludingDiagnostics("BCP395").Should().HaveDiagnostics(new[] { + result.Should().HaveDiagnostics(new[] { ("BCP028", DiagnosticLevel.Error, "Identifier \"az\" is declared multiple times. Remove or rename the duplicates."), ("BCP028", DiagnosticLevel.Error, "Identifier \"az\" is declared multiple times. Remove or rename the duplicates."), }); @@ -409,7 +408,7 @@ public async Task Config_with_optional_properties_can_be_skipped() [TestMethod] public async Task MicrosoftGraph_imports_succeed_with_preview_feature_enabled() { - var result = await CompilationHelper.RestoreAndCompile(await GetServices(), @"provider 'microsoftGraph@1.0.0' as graph"); + var result = await CompilationHelper.RestoreAndCompile(await GetServices(), @"provider microsoftGraph as graph"); result.Should().HaveDiagnostics(new[] { ("BCP204", DiagnosticLevel.Error, "Provider namespace \"microsoftGraph\" is not recognized."), @@ -418,9 +417,9 @@ public async Task MicrosoftGraph_imports_succeed_with_preview_feature_enabled() var serviceWithPreview = new ServiceBuilder() .WithFeatureOverrides(new(TestContext, ExtensibilityEnabled: true, MicrosoftGraphPreviewEnabled: true)); - result = await CompilationHelper.RestoreAndCompile(serviceWithPreview, @"provider 'microsoftGraph@1.0.0' as graph"); + result = await CompilationHelper.RestoreAndCompile(serviceWithPreview, @"provider microsoftGraph as graph"); - result.ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.Should().NotHaveAnyDiagnostics(); } } } diff --git a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs index ac3cde84765..a4499325869 100644 --- a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs +++ b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs @@ -5683,7 +5683,7 @@ public void Test_Issue12347() .WithFeatureOverrides(new(TestContext, ExtensibilityEnabled: true)) .WithConfigurationPatch(x => x.WithAnalyzers(x.Analyzers.SetValue("core.rules.use-recent-api-versions.level", "error"))), ("main.bicep", """ - provider 'kubernetes@1.0.0' with { + provider kubernetes with { kubeConfig: 'config' namespace: '' } as k8s @@ -5721,7 +5721,7 @@ public void Test_Issue12347() } """)); - result.ExcludingLinterDiagnostics().ExcludingDiagnostics("BCP395").Should().NotHaveAnyDiagnostics(); + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); } // https://github.com/Azure/bicep/issues/13250 diff --git a/src/Bicep.Core.Samples/Files/user_submitted/extensibility/aks/modules/kubernetes.bicep b/src/Bicep.Core.Samples/Files/user_submitted/extensibility/aks/modules/kubernetes.bicep index 93a43f07fcf..bd9b016db53 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/extensibility/aks/modules/kubernetes.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/extensibility/aks/modules/kubernetes.bicep @@ -1,7 +1,7 @@ @secure() param kubeConfig string -provider 'kubernetes@1.0.0' with { +provider kubernetes with { kubeConfig: kubeConfig namespace: 'default' } diff --git a/src/Bicep.Core.Samples/Files/user_submitted/extensibility/microsoftGraph/main.bicep b/src/Bicep.Core.Samples/Files/user_submitted/extensibility/microsoftGraph/main.bicep index f77e2ce98b4..8027add1f54 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/extensibility/microsoftGraph/main.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/extensibility/microsoftGraph/main.bicep @@ -1,4 +1,4 @@ -provider 'microsoftGraph@1.0.0' as graph +provider microsoftGraph as graph param appRoleId string = 'bc76c90e-eb7f-4a29-943b-49e88762d09d' param scopeId string = 'f761933c-643b-424f-a169-f9313d23a913' diff --git a/src/Bicep.Core.Samples/Files/user_submitted/extensibility/microsoftGraph/main.existing.bicep b/src/Bicep.Core.Samples/Files/user_submitted/extensibility/microsoftGraph/main.existing.bicep index 583d8f75f69..85a375b4166 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/extensibility/microsoftGraph/main.existing.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/extensibility/microsoftGraph/main.existing.bicep @@ -1,4 +1,4 @@ -provider 'microsoftGraph@1.0.0' +provider microsoftGraph resource resourceApp 'Microsoft.Graph/applications@beta' existing = { uniqueName: 'resourceApp' diff --git a/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/UseRecentApiVersionRuleTests.cs b/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/UseRecentApiVersionRuleTests.cs index c1323a177f6..a1dc2f3d3e1 100644 --- a/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/UseRecentApiVersionRuleTests.cs +++ b/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/UseRecentApiVersionRuleTests.cs @@ -1891,7 +1891,7 @@ public void ProvidesFixWithMostRecentVersion_CustomAgeZero() public void LinterIgnoresNotAzureResources() { CompileAndTestWithFakeDateAndTypes(@" - provider 'kubernetes@1.0.0' with { + provider kubernetes with { namespace: 'default' kubeConfig: '' } diff --git a/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs b/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs index a705d6d32fb..87d50894207 100644 --- a/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs @@ -1766,9 +1766,9 @@ public async Task Provider_completions_work_if_feature_enabled() var fileWithCursors = @" | - provider 'ns1@1.0.0' | - provider 'ns2@1.0.0' a| - provider 'ns3@1.0.0' as| + provider ns1 | + provider ns2 a| + provider ns3 as| provider | provider a| "; @@ -1778,8 +1778,8 @@ public async Task Provider_completions_work_if_feature_enabled() c => c!.Select(x => x.Label).Should().Equal("with", "as"), c => c!.Select(x => x.Label).Should().Equal("with", "as"), c => c!.Select(x => x.Label).Should().BeEmpty(), - c => c!.Select(x => x.Label).Should().Equal($"'az@{BicepTestConstants.BuiltinAzProviderVersion}'", "'kubernetes@1.0.0'", "'sys@1.0.0'"), - c => c!.Select(x => x.Label).Should().BeEmpty() + c => c!.Select(x => x.Label).Should().Equal($"az", "kubernetes", "sys"), + c => c!.Select(x => x.Label).Should().Equal($"az", "kubernetes", "sys") ), '|'); @@ -1800,7 +1800,7 @@ public async Task Provider_configuration_completions_work() { { var fileWithCursors = @" -provider 'kubernetes@1.0.0' with | as k8s +provider kubernetes with | as k8s "; var (text, cursor) = ParserHelper.GetFileWithSingleCursor(fileWithCursors, '|'); @@ -1812,7 +1812,7 @@ public async Task Provider_configuration_completions_work() var updatedFile = file.ApplyCompletion(completions, "required-properties"); updatedFile.Should().HaveSourceText(@" -provider 'kubernetes@1.0.0' with { +provider kubernetes with { kubeConfig: $1 namespace: $2 }| as k8s @@ -1821,7 +1821,7 @@ public async Task Provider_configuration_completions_work() { var fileWithCursors = @" -provider 'kubernetes@1.0.0' with { +provider kubernetes with { | } "; @@ -1835,7 +1835,7 @@ public async Task Provider_configuration_completions_work() var updatedFile = file.ApplyCompletion(completions, "kubeConfig"); updatedFile.Should().HaveSourceText(@" -provider 'kubernetes@1.0.0' with { +provider kubernetes with { kubeConfig:| } "); diff --git a/src/Bicep.LangServer.IntegrationTests/Files/ImportKubernetesManifest/azure-vote-all-in-one-redis/manifest.bicep b/src/Bicep.LangServer.IntegrationTests/Files/ImportKubernetesManifest/azure-vote-all-in-one-redis/manifest.bicep index 6d284be8cb8..ce925bed795 100644 --- a/src/Bicep.LangServer.IntegrationTests/Files/ImportKubernetesManifest/azure-vote-all-in-one-redis/manifest.bicep +++ b/src/Bicep.LangServer.IntegrationTests/Files/ImportKubernetesManifest/azure-vote-all-in-one-redis/manifest.bicep @@ -1,7 +1,7 @@ @secure() param kubeConfig string -provider 'kubernetes@1.0.0' with { +provider kubernetes with { namespace: 'default' kubeConfig: kubeConfig } diff --git a/src/Bicep.LangServer.IntegrationTests/Files/ImportKubernetesManifest/wordpress/manifest.bicep b/src/Bicep.LangServer.IntegrationTests/Files/ImportKubernetesManifest/wordpress/manifest.bicep index f2947f50b63..b564930ff5c 100644 --- a/src/Bicep.LangServer.IntegrationTests/Files/ImportKubernetesManifest/wordpress/manifest.bicep +++ b/src/Bicep.LangServer.IntegrationTests/Files/ImportKubernetesManifest/wordpress/manifest.bicep @@ -1,7 +1,7 @@ @secure() param kubeConfig string -provider 'kubernetes@1.0.0' with { +provider kubernetes with { namespace: 'default' kubeConfig: kubeConfig } diff --git a/src/Bicep.LangServer.UnitTests/BicepCompletionProviderTests.cs b/src/Bicep.LangServer.UnitTests/BicepCompletionProviderTests.cs index d1474cd35e5..c0ec5535042 100644 --- a/src/Bicep.LangServer.UnitTests/BicepCompletionProviderTests.cs +++ b/src/Bicep.LangServer.UnitTests/BicepCompletionProviderTests.cs @@ -410,16 +410,15 @@ public async Task CommentShouldNotGiveAnyCompletions(string codeFragment) [TestMethod] public async Task CompletionsShouldContainMicrosoftGraphWhenPreviewFeatureEnabled() { - var codeFragment = @"provider 'microsoftGraph@1.0.0' as graph"; + var (contents, cursor) = ParserHelper.GetFileWithSingleCursor("provider m| as graph"); + var completionProvider = CreateProvider(); - var offset = 9; var featureOverrides = new FeatureProviderOverrides(ExtensibilityEnabled: true, MicrosoftGraphPreviewEnabled: true); var serviceWithGraph = new ServiceBuilder().WithFeatureOverrides(featureOverrides); - var compilationWithMSGraph = serviceWithGraph.BuildCompilation(codeFragment); - compilationWithMSGraph.GetEntrypointSemanticModel().GetAllDiagnostics().Where(d => !d.Code.Equals("BCP395")).Should().BeEmpty(); + var compilationWithMSGraph = serviceWithGraph.BuildCompilation(contents); var features = new OverriddenFeatureProvider(new FeatureProvider(BicepTestConstants.BuiltInConfiguration), featureOverrides); - var completionsWithMSGraph = await completionProvider.GetFilteredCompletions(compilationWithMSGraph, BicepCompletionContext.Create(features, compilationWithMSGraph, offset), CancellationToken.None); + var completionsWithMSGraph = await completionProvider.GetFilteredCompletions(compilationWithMSGraph, BicepCompletionContext.Create(features, compilationWithMSGraph, cursor), CancellationToken.None); completionsWithMSGraph.Should().Contain(c => c.Label.Contains("microsoftGraph")); } diff --git a/src/Bicep.LangServer/Completions/BicepCompletionContext.cs b/src/Bicep.LangServer/Completions/BicepCompletionContext.cs index e2b836750d1..bcd09a14273 100644 --- a/src/Bicep.LangServer/Completions/BicepCompletionContext.cs +++ b/src/Bicep.LangServer/Completions/BicepCompletionContext.cs @@ -24,23 +24,23 @@ public record IndexedSyntaxContext(T Syntax, int ArgumentIndex) where T : Syn private static readonly CompositeSyntaxPattern ExpectingImportSpecification = CompositeSyntaxPattern.Create( cursor: '|', "provider |", - "provider |'kuber'", - "provider 'kuber|'"); + "provider |kuber", + "provider kuber|"); private static readonly CompositeSyntaxPattern ExpectingImportWithOrAsKeyword = CompositeSyntaxPattern.Create( cursor: '|', - "provider 'kubernetes@1.0.0' |", - "provider 'kubernetes@1.0.0' a|", - "provider 'kubernetes@1.0.0' |b"); + "provider kubernetes |", + "provider kubernetes a|", + "provider kubernetes |b"); private static readonly CompositeSyntaxPattern ExpectingImportConfig = CompositeSyntaxPattern.Create( cursor: '|', - "provider 'kubernetes@1.0.0' with |", - "provider 'kubernetes@1.0.0' with | as foo"); + "provider kubernetes with |", + "provider kubernetes with | as foo"); private static readonly SyntaxPattern ExpectingImportAsKeyword = SyntaxPattern.Create( cursor: '|', - "provider 'kubernetes@1.0.0' with { foo: true } |"); + "provider kubernetes with { foo: true } |"); // completions will replace only these token types // all others will result in an insertion upon completion commit diff --git a/src/Bicep.LangServer/Completions/BicepCompletionProvider.cs b/src/Bicep.LangServer/Completions/BicepCompletionProvider.cs index 6241730dc83..b1fff7fd553 100644 --- a/src/Bicep.LangServer/Completions/BicepCompletionProvider.cs +++ b/src/Bicep.LangServer/Completions/BicepCompletionProvider.cs @@ -2047,8 +2047,7 @@ private IEnumerable GetProviderImportCompletions(SemanticModel m foreach (var setting in availableNamespaceSettingsList.OrderBy(x => x.BicepProviderName, LanguageConstants.IdentifierComparer)) { - var completionText = $"'{setting.BicepProviderName}@{setting.ArmTemplateProviderVersion}'"; - + var completionText = setting.BicepProviderName; yield return CompletionItemBuilder.Create(CompletionItemKind.Folder, completionText) .WithSortText(GetSortText(completionText, CompletionPriority.High)) .WithDetail(completionText) diff --git a/src/Bicep.LangServer/Handlers/BicepHoverHandler.cs b/src/Bicep.LangServer/Handlers/BicepHoverHandler.cs index 2521333f195..11b5637a8bb 100644 --- a/src/Bicep.LangServer/Handlers/BicepHoverHandler.cs +++ b/src/Bicep.LangServer/Handlers/BicepHoverHandler.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System.Text; +using Bicep.Core; using Bicep.Core.Extensions; using Bicep.Core.Navigation; using Bicep.Core.Registry; @@ -81,7 +82,7 @@ public class BicepHoverHandler : HoverHandlerBase { case ProviderNamespaceSymbol provider: return AsMarkdown(MarkdownHelper.CodeBlockWithDescription( - $"import {provider.Name}", TryGetDescription(result, provider))); + $"{LanguageConstants.ProviderKeyword} {provider.Name}", TryGetDescription(result, provider))); case MetadataSymbol metadata: return AsMarkdown(MarkdownHelper.CodeBlockWithDescription( diff --git a/src/Bicep.LangServer/Handlers/ImportKubernetesManifestHandler.cs b/src/Bicep.LangServer/Handlers/ImportKubernetesManifestHandler.cs index 2041e3722eb..e1de4abf7d8 100644 --- a/src/Bicep.LangServer/Handlers/ImportKubernetesManifestHandler.cs +++ b/src/Bicep.LangServer/Handlers/ImportKubernetesManifestHandler.cs @@ -62,7 +62,7 @@ public string Decompile(string bicepFilePath, string manifestContents, Telemetry new ProviderDeclarationSyntax( [], SyntaxFactory.ProviderKeywordToken, - SyntaxFactory.CreateStringLiteralWithTextSpan($"'{K8sNamespaceType.BuiltInName}@{K8sNamespaceType.BuiltInVersion}'"), + SyntaxFactory.CreateIdentifierWithTrailingSpace(K8sNamespaceType.BuiltInName), new ProviderWithClauseSyntax( SyntaxFactory.CreateToken(TokenType.WithKeyword), SyntaxFactory.CreateObject(