From 19bddfdd5b4be1b2c3dd397dcd265ec56ebf4210 Mon Sep 17 00:00:00 2001 From: Shenglong Li Date: Thu, 20 Jun 2024 16:22:48 -0700 Subject: [PATCH 1/3] Replace provider with extension --- .../PublishProviderCommandTests.cs | 2 +- ...ntralizedProviderVersionManagementTests.cs | 4 +- .../DynamicAzTypesTests.cs | 24 +++---- .../Extensibility/RadiusCompatibilityTests.cs | 4 +- .../ExtensibilityTests.cs | 46 ++++++------- .../OutputsTests.cs | 2 +- .../ParametersTests.cs | 2 +- .../ProviderImportTests.cs | 68 +++++++++---------- .../RegistryProviderTests.cs | 52 +++++++------- .../ScenarioTests.cs | 2 +- .../ResourceTypeProviderFactoryTests.cs | 4 +- .../aks/modules/kubernetes.bicep | 2 +- .../extensibility/microsoftGraph/main.bicep | 2 +- .../microsoftGraph/main.existing.bicep | 2 +- .../ProviderConfigurationTests.cs | 4 +- .../Diagnostics/DiagnosticBuilder.cs | 24 +++---- src/Bicep.Core/LanguageConstants.cs | 1 + src/Bicep.Core/Parsing/Parser.cs | 15 ++-- .../Syntax/ProviderDeclarationSyntax.cs | 2 +- .../TypeSystem/TypeAssignmentVisitor.cs | 5 +- .../CodeActionTests.cs | 13 +++- 21 files changed, 146 insertions(+), 134 deletions(-) diff --git a/src/Bicep.Cli.IntegrationTests/PublishProviderCommandTests.cs b/src/Bicep.Cli.IntegrationTests/PublishProviderCommandTests.cs index 9768f6cd4e6..31d78437436 100644 --- a/src/Bicep.Cli.IntegrationTests/PublishProviderCommandTests.cs +++ b/src/Bicep.Cli.IntegrationTests/PublishProviderCommandTests.cs @@ -103,7 +103,7 @@ public async Task Publish_provider_should_succeed_to_filesystem() var services = new ServiceBuilder().WithFileSystem(fs).WithFeatureOverrides(new(ExtensibilityEnabled: true, ProviderRegistry: true)); var compileResult = await CompilationHelper.RestoreAndCompile(services, """ -provider '../../target/provider.tgz' +extension '../../target/provider.tgz' resource fooRes 'fooType@v1' = { identifier: 'foo' diff --git a/src/Bicep.Core.IntegrationTests/CentralizedProviderVersionManagementTests.cs b/src/Bicep.Core.IntegrationTests/CentralizedProviderVersionManagementTests.cs index 683db256b6c..936d6d8f42e 100644 --- a/src/Bicep.Core.IntegrationTests/CentralizedProviderVersionManagementTests.cs +++ b/src/Bicep.Core.IntegrationTests/CentralizedProviderVersionManagementTests.cs @@ -23,7 +23,7 @@ public class CentralizedProviderVersionManagementTests : TestBase public void ProvidersConfig_SupportForConfigManagedProviderDeclarationSyntax_When_ProviderIsBuiltIn(string providerIdentifier, bool shouldSucceed, (string code, DiagnosticLevel level, string message)[] expectedDiagnostics) { var result = CompilationHelper.Compile(Services, @$" - provider {providerIdentifier} + extension {providerIdentifier} "); if (shouldSucceed) @@ -55,7 +55,7 @@ public static IEnumerable ProvidersConfig_SupportForConfigManagedProvi "kubernetes", false, new (string, DiagnosticLevel, string)[] { - ("BCP206", DiagnosticLevel.Error, "Provider namespace \"kubernetes\" requires configuration, but none was provided.") } }; + ("BCP206", DiagnosticLevel.Error, "Extension \"kubernetes\" requires configuration, but none was provided.") } }; } } } diff --git a/src/Bicep.Core.IntegrationTests/DynamicAzTypesTests.cs b/src/Bicep.Core.IntegrationTests/DynamicAzTypesTests.cs index e4fcb919a46..b0c0989026d 100644 --- a/src/Bicep.Core.IntegrationTests/DynamicAzTypesTests.cs +++ b/src/Bicep.Core.IntegrationTests/DynamicAzTypesTests.cs @@ -64,7 +64,7 @@ public async Task Az_namespace_can_be_used_without_configuration() { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, ("main.bicep", @$" - provider 'br/public:az:{BicepTestConstants.BuiltinAzProviderVersion}' + extension 'br/public:az:{BicepTestConstants.BuiltinAzProviderVersion}' ")); result.Should().GenerateATemplate(); @@ -76,12 +76,12 @@ public async Task Az_namespace_errors_with_configuration() { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, @$" - provider 'br/public:az:{BicepTestConstants.BuiltinAzProviderVersion}' with {{}} + extension 'br/public:az:{BicepTestConstants.BuiltinAzProviderVersion}' with {{}} "); result.Should().NotGenerateATemplate(); result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { - ("BCP205", DiagnosticLevel.Error, "Provider namespace \"az\" does not support configuration."), + ("BCP205", DiagnosticLevel.Error, "Extension \"az\" does not support configuration."), }); } @@ -90,7 +90,7 @@ public async Task Az_namespace_can_be_used_with_alias() { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, @$" - provider 'br/public:az:{BicepTestConstants.BuiltinAzProviderVersion}' as testAlias + extension 'br/public:az:{BicepTestConstants.BuiltinAzProviderVersion}' as testAlias "); result.Should().GenerateATemplate(); @@ -114,7 +114,7 @@ public async Task Az_namespace_can_be_used_with_bicepconfig_provider_alias() """)); var result = await CompilationHelper.RestoreAndCompile(services, @$" - provider 'br/customAlias:az:{BicepTestConstants.BuiltinAzProviderVersion}' + extension 'br/customAlias:az:{BicepTestConstants.BuiltinAzProviderVersion}' "); result.Should().GenerateATemplate(); @@ -128,7 +128,7 @@ public async Task Inlined_Az_namespace_alias_is_not_specified_in_config_yields_d .WithFeatureOverrides(new(ExtensibilityEnabled: true, DynamicTypeLoadingEnabled: true)); var result = await CompilationHelper.RestoreAndCompile(services, @" - provider 'br/notFound:az:0.2.661' + extension 'br/notFound:az:0.2.661' "); result.Should().NotGenerateATemplate(); @@ -160,7 +160,7 @@ await RegistryHelper.PublishModuleToRegistryAsync( // ACT var result = await CompilationHelper.RestoreAndCompile(services, @$" - provider '{testArtifact.ToSpecificationString(':')}' + extension '{testArtifact.ToSpecificationString(':')}' "); // ASSERT @@ -184,7 +184,7 @@ public async Task Bicep_compiler_handles_corrupted_provider_package_gracefully( // ACT var result = await CompilationHelper.RestoreAndCompile(services, @$" - provider '{testArtifactAddress.ToSpecificationString(':')}' + extension '{testArtifactAddress.ToSpecificationString(':')}' "); // ASSERT @@ -226,7 +226,7 @@ public async Task Repository_not_found_in_registry( // ACT var result = await CompilationHelper.RestoreAndCompile(services, @$" - provider '{artifactRegistryAddress.ToSpecificationString(':')}' + extension '{artifactRegistryAddress.ToSpecificationString(':')}' "); // ASSERT @@ -315,7 +315,7 @@ public async Task External_Az_namespace_can_be_loaded_from_configuration() } """)); var result = await CompilationHelper.RestoreAndCompile(services, ("main.bicep", @$" - provider az + extension az ")); result.Should().GenerateATemplate(); @@ -333,7 +333,7 @@ public async Task BuiltIn_Az_namespace_can_be_loaded_from_configuration() // "implicitProviders": ["az"] // } var result = await CompilationHelper.RestoreAndCompile(services, ("main.bicep", @$" - provider az + extension az ")); result.Should().GenerateATemplate(); @@ -357,7 +357,7 @@ public async Task Az_namespace_can_be_loaded_dynamically_using_provider_configur """)); //ACT var result = await CompilationHelper.RestoreAndCompile(services, ("main.bicep", @$" - provider az + extension az ")); //ASSERT result.Should().GenerateATemplate(); diff --git a/src/Bicep.Core.IntegrationTests/Extensibility/RadiusCompatibilityTests.cs b/src/Bicep.Core.IntegrationTests/Extensibility/RadiusCompatibilityTests.cs index 337d8021c1d..495d91451c7 100644 --- a/src/Bicep.Core.IntegrationTests/Extensibility/RadiusCompatibilityTests.cs +++ b/src/Bicep.Core.IntegrationTests/Extensibility/RadiusCompatibilityTests.cs @@ -43,7 +43,7 @@ public async Task Radius_identifier_passing_works_as_defined() var services = await GetServicesWithPrepublishedTypes(); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/test/radius:1.0.0' +extension 'br:example.azurecr.io/test/radius:1.0.0' @description('The base name of the test, used to qualify resources and namespaces') param basename string @@ -81,7 +81,7 @@ public async Task Radius_use_of_existing_works() var services = await GetServicesWithPrepublishedTypes(); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/test/radius:1.0.0' +extension 'br:example.azurecr.io/test/radius:1.0.0' param bucketName string diff --git a/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs b/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs index 8c22c00fb59..fba4e655c76 100644 --- a/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs +++ b/src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs @@ -34,7 +34,7 @@ public class ExtensibilityTests : TestBase public void Bar_import_bad_config_is_blocked() { var result = CompilationHelper.Compile(Services, @" -provider bar with { +extension bar with { madeUpProperty: 'asdf' } as stg "); @@ -48,11 +48,11 @@ provider bar with { public void Bar_import_can_be_duplicated() { var result = CompilationHelper.Compile(Services, """ - provider bar with { + extension bar with { connectionString: 'connectionString1' } as stg - provider bar with { + extension bar with { connectionString: 'connectionString2' } as stg2 """); @@ -63,7 +63,7 @@ provider bar with { public void Bar_import_basic_test() { var result = CompilationHelper.Compile(Services, """ - provider bar with { + extension bar with { connectionString: 'asdf' } as stg @@ -84,11 +84,11 @@ provider bar with { public void Ambiguous_type_references_return_errors() { var result = CompilationHelper.Compile(Services, """ - provider bar with { + extension bar with { connectionString: 'asdf' } as stg - provider bar with { + extension bar with { connectionString: 'asdf' } as stg2 @@ -101,11 +101,11 @@ provider bar with { }); result = CompilationHelper.Compile(Services, """ - provider bar with { + extension bar with { connectionString: 'asdf' } as stg - provider bar with { + extension bar with { connectionString: 'asdf' } as stg2 @@ -120,7 +120,7 @@ provider bar with { public void Bar_import_basic_test_loops_and_referencing() { var result = CompilationHelper.Compile(Services, """ - provider bar with { + extension bar with { connectionString: 'asdf' } as stg @@ -160,7 +160,7 @@ provider bar with { public void Foo_import_basic_test_loops_and_referencing() { var result = CompilationHelper.Compile(Services, """ - provider foo as foo + extension foo as foo param numApps int resource myApp 'application' = { @@ -190,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 + extension foo resource myApp 'application' existing = { name: 'foo' @@ -206,7 +206,7 @@ provider foo // oops! let's change it to 'uniqueName' result = CompilationHelper.Compile(Services, """ - provider foo as foo + extension foo as foo resource myApp 'application' existing = { uniqueName: 'foo' @@ -223,7 +223,7 @@ provider foo as foo public void Kubernetes_import_existing_warns_with_readonly_fields() { var result = CompilationHelper.Compile(Services, """ - provider kubernetes with { + extension kubernetes with { namespace: 'default' kubeConfig: '' } @@ -253,12 +253,12 @@ provider kubernetes with { public void Kubernetes_competing_imports_are_blocked() { var result = CompilationHelper.Compile(Services, @" -provider kubernetes with { +extension kubernetes with { namespace: 'default' kubeConfig: '' } -provider kubernetes with { +extension kubernetes with { namespace: 'default' kubeConfig: '' } @@ -277,7 +277,7 @@ provider kubernetes with { public void Kubernetes_import_existing_resources() { var result = CompilationHelper.Compile(Services, @" -provider kubernetes with { +extension kubernetes with { namespace: 'default' kubeConfig: '' } @@ -313,7 +313,7 @@ provider kubernetes with { public void Kubernetes_import_existing_connectionstring_test() { var result = CompilationHelper.Compile(Services, @" -provider kubernetes with { +extension kubernetes with { namespace: 'default' kubeConfig: '' } @@ -351,7 +351,7 @@ provider kubernetes with { public void Kubernetes_CustomResourceType_EmitWarning() { var result = CompilationHelper.Compile(Services, """ - provider kubernetes with { + extension kubernetes with { namespace: 'default' kubeConfig: '' } @@ -372,7 +372,7 @@ provider kubernetes with { public void Kubernetes_AmbiguousFallbackType_MustFullyQualify() { var result = CompilationHelper.Compile(Services, """ - provider kubernetes with { + extension kubernetes with { namespace: 'default' kubeConfig: '' } @@ -406,7 +406,7 @@ provider kubernetes with { public void Bar_import_basic_test_with_qualified_type() { var result = CompilationHelper.Compile(Services, """ - provider bar with { + extension bar with { connectionString: 'asdf' } as stg @@ -427,7 +427,7 @@ provider bar with { public void Invalid_namespace_qualifier_returns_error() { var result = CompilationHelper.Compile(Services, """ - provider bar with { + extension bar with { connectionString: 'asdf' } as stg @@ -452,7 +452,7 @@ provider bar with { public void Child_resource_with_parent_namespace_mismatch_returns_error() { var result = CompilationHelper.Compile(Services, @" -provider bar with { +extension bar with { connectionString: 'asdf' } as stg @@ -500,7 +500,7 @@ param accountName string @secure() param connectionString string -provider bar with { +extension bar with { connectionString: connectionString } as stg diff --git a/src/Bicep.Core.IntegrationTests/OutputsTests.cs b/src/Bicep.Core.IntegrationTests/OutputsTests.cs index 0e3c1cde212..8ee63c3b0a2 100644 --- a/src/Bicep.Core.IntegrationTests/OutputsTests.cs +++ b/src/Bicep.Core.IntegrationTests/OutputsTests.cs @@ -235,7 +235,7 @@ public void Output_cannot_use_extensibility_resource_type() { var result = CompilationHelper.Compile(ServicesWithExtensibility, """ - provider bar with { + extension bar with { connectionString: 'asdf' } as stg diff --git a/src/Bicep.Core.IntegrationTests/ParametersTests.cs b/src/Bicep.Core.IntegrationTests/ParametersTests.cs index f39b86e9fd9..c890a906ce6 100644 --- a/src/Bicep.Core.IntegrationTests/ParametersTests.cs +++ b/src/Bicep.Core.IntegrationTests/ParametersTests.cs @@ -177,7 +177,7 @@ param p resource 'Some.Fake/Type@2019-06-01' public void Parameter_cannot_use_extensibility_resource_type() { var result = CompilationHelper.Compile(ServicesWithExtensibility, """ - provider bar with { + extension bar with { connectionString: 'asdf' } as stg diff --git a/src/Bicep.Core.IntegrationTests/ProviderImportTests.cs b/src/Bicep.Core.IntegrationTests/ProviderImportTests.cs index f98b6a42ae0..b45996e89ab 100644 --- a/src/Bicep.Core.IntegrationTests/ProviderImportTests.cs +++ b/src/Bicep.Core.IntegrationTests/ProviderImportTests.cs @@ -53,10 +53,10 @@ public async Task Providers_are_disabled_unless_feature_is_enabled() { var services = new ServiceBuilder(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider az + extension az """); result.Should().HaveDiagnostics(new[] { - ("BCP203", DiagnosticLevel.Error, "Using provider statements requires enabling EXPERIMENTAL feature \"Extensibility\"."), + ("BCP203", DiagnosticLevel.Error, "Using extension declaration requires enabling EXPERIMENTAL feature \"Extensibility\"."), }); } @@ -65,13 +65,13 @@ public async Task Provider_Statement_Without_Specification_String_Should_Emit_Di { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, @" -provider +extension "); result.Should().HaveDiagnostics([ ("BCP201", DiagnosticLevel.Error, """ - Expected a provider specification string with a valid format at this location. Valid formats: - * "br:/:" - * "br/::" + Expected an extension specification string with a valid format at this location. Valid formats: + * "br:/:" + * "br/::" """) ]); } @@ -81,7 +81,7 @@ public async Task Provider_Statement_With_Invalid_Keyword_Should_Emit_Diagnostic { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider sys blahblah + extension sys blahblah """); result.Should().HaveDiagnostics(new[] { ("BCP305", DiagnosticLevel.Error, "Expected the \"with\" keyword, \"as\" keyword, or a new line character at this location."), @@ -93,7 +93,7 @@ public async Task Provider_Statement_Without_Brace_Should_Raise_Error() { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider kubernetes with + extension kubernetes with """); result.Should().HaveDiagnostics(new[] { ("BCP018", DiagnosticLevel.Error, "Expected the \"{\" character at this location."), @@ -105,7 +105,7 @@ public async Task Provider_Statement_Without_As_Keyword_Should_Raise_Error() { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider kubernetes with { + extension kubernetes with { kubeConfig: 'foo' namespace: 'bar' } something @@ -120,13 +120,13 @@ public async Task Provider_Statement_Without_Alias_Name_Should_Raise_Error() { var services = await GetServices(); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider kubernetes with { + extension kubernetes with { kubeConfig: 'foo' namespace: 'bar' } as """); result.Should().HaveDiagnostics(new[] { - ("BCP202", DiagnosticLevel.Error, "Expected a provider alias name at this location."), + ("BCP202", DiagnosticLevel.Error, "Expected an extension alias name at this location."), }); } @@ -135,10 +135,10 @@ 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 as + extension sys as """); result.Should().HaveDiagnostics(new[] { - ("BCP202", DiagnosticLevel.Error, "Expected a provider alias name at this location."), + ("BCP202", DiagnosticLevel.Error, "Expected an extension alias name at this location."), }); } @@ -146,12 +146,12 @@ provider sys as public async Task Import_configuration_is_blocked_by_default() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider az with { + extension az with { foo: 'bar' } """); result.Should().HaveDiagnostics(new[] { - ("BCP205", DiagnosticLevel.Error, "Provider namespace \"az\" does not support configuration."), + ("BCP205", DiagnosticLevel.Error, "Extension \"az\" does not support configuration."), }); } @@ -159,10 +159,10 @@ provider az with { public async Task Imports_return_error_with_unrecognized_namespace() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), @" -provider madeUpNamespace +extension madeUpNamespace "); result.Should().HaveDiagnostics(new[] { - ("BCP204", DiagnosticLevel.Error, "Provider namespace \"madeUpNamespace\" is not recognized."), + ("BCP204", DiagnosticLevel.Error, "Extension \"madeUpNamespace\" is not recognized."), }); } @@ -170,7 +170,7 @@ provider madeUpNamespace public async Task Using_import_statements_frees_up_the_namespace_symbol() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider az as newAz + extension az as newAz var az = 'Fake AZ!' var myRg = newAz.resourceGroup() @@ -186,8 +186,8 @@ provider az as newAz public async Task You_can_swap_imported_namespaces_if_you_really_really_want_to() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider az as sys - provider sys as az + extension az as sys + extension sys as az var myRg = sys.resourceGroup() @@ -204,7 +204,7 @@ provider sys as az public async Task Overwriting_single_built_in_namespace_with_import_is_prohibited() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider az as sys + extension az as sys var myRg = sys.resourceGroup() @@ -218,11 +218,11 @@ provider az as sys public async Task Singleton_imports_cannot_be_used_multiple_times() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider az as az1 - provider az as az2 + extension az as az1 + extension az as az2 - provider sys as sys1 - provider sys as sys2 + extension sys as sys1 + extension sys as sys2 """); result.Should().HaveDiagnostics(new[] { @@ -237,8 +237,8 @@ provider sys as sys2 public async Task Import_names_must_not_conflict_with_other_symbols() { var result = await CompilationHelper.RestoreAndCompile(await GetServices(), """ - provider az - provider kubernetes with { + extension az + extension kubernetes with { kubeConfig: '' namespace: '' } as az @@ -305,8 +305,8 @@ public async Task Ambiguous_function_references_must_be_qualified() """)); var result = await CompilationHelper.RestoreAndCompile(services, @" - provider ns1 - provider ns2 + extension ns1 + extension ns2 output ambiguousResult string = dupeFunc() output ns1Result string = ns1Func() @@ -319,8 +319,8 @@ provider ns2 // fix by fully-qualifying result = await CompilationHelper.RestoreAndCompile(services, @" - provider ns1 - provider ns2 + extension ns1 + extension ns2 output ambiguousResult string = ns1.dupeFunc() output ns1Result string = ns1Func() @@ -370,10 +370,10 @@ public async Task Config_with_optional_properties_can_be_skipped() """)); var result = await CompilationHelper.RestoreAndCompile(services, """ - provider mockNs with { + extension mockNs with { optionalConfig: 'blah blah' } as ns1 - provider mockNs + extension mockNs """); result.Should().NotHaveAnyDiagnostics(); @@ -382,7 +382,7 @@ provider mockNs [TestMethod] public async Task MicrosoftGraph_imports_succeed_default() { - var result = await CompilationHelper.RestoreAndCompile(await GetServices(), @"provider microsoftGraph as graph"); + var result = await CompilationHelper.RestoreAndCompile(await GetServices(), @"extension microsoftGraph as graph"); result.Should().NotHaveAnyDiagnostics(); } diff --git a/src/Bicep.Core.IntegrationTests/RegistryProviderTests.cs b/src/Bicep.Core.IntegrationTests/RegistryProviderTests.cs index b04d7bb06fd..5407b8f2e92 100644 --- a/src/Bicep.Core.IntegrationTests/RegistryProviderTests.cs +++ b/src/Bicep.Core.IntegrationTests/RegistryProviderTests.cs @@ -57,7 +57,7 @@ public async Task Providers_published_to_a_registry_can_be_compiled() await RegistryHelper.PublishProviderToRegistryAsync(services.Build(), "/types/index.json", $"br:{registry}/{repository}:1.2.3"); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/test/provider/http:1.2.3' +extension 'br:example.azurecr.io/test/provider/http:1.2.3' resource dadJoke 'request@v1' = { uri: 'https://icanhazdadjoke.com' @@ -88,7 +88,7 @@ public async Task Providers_published_to_filesystem_can_be_compiled() var bicepPath = Path.Combine(tempDirectory, "main.bicep"); await File.WriteAllTextAsync(bicepPath, """ -provider './provider.tgz' +extension './provider.tgz' resource fooRes 'fooType@v1' = { identifier: 'foo' @@ -115,7 +115,7 @@ public async Task Existing_resources_are_permitted_through_3p_type_registry() var services = await ProviderTestHelper.GetServiceBuilderWithPublishedProvider(ThirdPartyTypeHelper.GetTestTypesTgz(), AllFeaturesEnabled); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' +extension 'br:example.azurecr.io/providers/foo:1.2.3' resource fooRes 'fooType@v1' existing = { } @@ -127,7 +127,7 @@ public async Task Existing_resources_are_permitted_through_3p_type_registry() }); result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' +extension 'br:example.azurecr.io/providers/foo:1.2.3' resource fooRes 'fooType@v1' existing = { identifier: 'foo' @@ -153,7 +153,7 @@ public async Task Third_party_namespace_errors_with_configuration() await RegistryHelper.PublishProviderToRegistryAsync(services.Build(), "/types/index.json", $"br:{registry}/{repository}:1.2.3"); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/test/provider/http:1.2.3' with {} +extension 'br:example.azurecr.io/test/provider/http:1.2.3' with {} resource dadJoke 'request@v1' = { uri: 'https://icanhazdadjoke.com' @@ -166,7 +166,7 @@ public async Task Third_party_namespace_errors_with_configuration() result.Should().NotGenerateATemplate(); result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { - ("BCP205", DiagnosticLevel.Error, "Provider namespace \"http\" does not support configuration.") + ("BCP205", DiagnosticLevel.Error, "Extension \"http\" does not support configuration.") }); } @@ -176,7 +176,7 @@ public async Task Resource_function_types_are_permitted_through_3p_type_registry var services = await ProviderTestHelper.GetServiceBuilderWithPublishedProvider(ThirdPartyTypeHelper.GetTestTypesTgz(), AllFeaturesEnabled); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' +extension 'br:example.azurecr.io/providers/foo:1.2.3' resource fooRes 'fooType@v1' existing = { identifier: 'foo' @@ -235,7 +235,7 @@ public async Task Third_party_imports_are_enabled_when_feature_is_enabled() await RegistryHelper.PublishProviderToRegistryAsync(services.Build(), "/types/index.json", $"br:{registry}/{repository}:1.2.3"); var result = await CompilationHelper.RestoreAndCompile(services, @$" -provider 'br:example.azurecr.io/test/provider/http:1.2.3' +extension 'br:example.azurecr.io/test/provider/http:1.2.3' "); result.Should().NotHaveAnyDiagnostics(); result.Template.Should().NotBeNull(); @@ -281,17 +281,17 @@ public async Task Third_party_imports_are_disabled_unless_feature_is_enabled() await RegistryHelper.PublishProviderToRegistryAsync(services.Build(), "/types/index.json", $"br:{registry}/{repository}:1.2.3"); var result = await CompilationHelper.RestoreAndCompile(services, @$" -provider 'br:example.azurecr.io/test/provider/http:1.2.3' +extension 'br:example.azurecr.io/test/provider/http:1.2.3' "); result.Should().HaveDiagnostics([ - ("BCP203", DiagnosticLevel.Error, "Using provider statements requires enabling EXPERIMENTAL feature \"Extensibility\"."), + ("BCP203", DiagnosticLevel.Error, "Using extension declaration requires enabling EXPERIMENTAL feature \"Extensibility\"."), ]); services = ProviderTestHelper.GetServiceBuilder(fileSystem, registry, repository, new(ExtensibilityEnabled: true)); var result2 = await CompilationHelper.RestoreAndCompile(services, @$" -provider 'br:example.azurecr.io/test/provider/http:1.2.3' +extension 'br:example.azurecr.io/test/provider/http:1.2.3' "); result2.Should().HaveDiagnostics([ ("BCP400", DiagnosticLevel.Error, """Fetching types from the registry requires enabling EXPERIMENTAL feature "ProviderRegistry"."""), @@ -306,7 +306,7 @@ public async Task Using_interpolated_strings_in_provider_declaration_syntax_resu var result = await CompilationHelper.RestoreAndCompile(services, """ var registryHost = 'example.azurecr.io' -provider 'br:${registryHost}/test/provider/http:1.2.3' +extension 'br:${registryHost}/test/provider/http:1.2.3' """); result.Should().NotGenerateATemplate(); result.Should().ContainDiagnostic("BCP303", DiagnosticLevel.Error, "String interpolation is unsupported for specifying the provider."); @@ -319,7 +319,7 @@ public async Task Cannot_import_az_without_dynamic_type_loading_enabled() services = services.WithFeatureOverrides(new(ExtensibilityEnabled: true, DynamicTypeLoadingEnabled: false)); var result = await CompilationHelper.RestoreAndCompile(services, @" -provider 'br:mcr.microsoft.com/bicep/provider/az:1.2.3' +extension 'br:mcr.microsoft.com/bicep/provider/az:1.2.3' "); result.Should().NotGenerateATemplate(); result.Should().HaveDiagnostics([ @@ -333,7 +333,7 @@ public async Task Missing_required_provider_configuration_blocks_compilation() var services = await ProviderTestHelper.GetServiceBuilderWithPublishedProvider(ThirdPartyTypeHelper.GetTestTypesTgzWithFallbackAndConfiguration(), AllFeaturesEnabled); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' +extension 'br:example.azurecr.io/providers/foo:1.2.3' resource dadJoke 'fooType@v1' = { identifier: 'foo' @@ -345,7 +345,7 @@ public async Task Missing_required_provider_configuration_blocks_compilation() result.Should().NotGenerateATemplate(); result.Should().HaveDiagnostics(new[]{ - ("BCP206", DiagnosticLevel.Error, "Provider namespace \"ThirdPartyProvider\" requires configuration, but none was provided.") + ("BCP206", DiagnosticLevel.Error, "Extension \"ThirdPartyProvider\" requires configuration, but none was provided.") }); } @@ -356,7 +356,7 @@ public async Task Correct_provider_configuration_result_in_successful_compilatio var services = await ProviderTestHelper.GetServiceBuilderWithPublishedProvider(ThirdPartyTypeHelper.GetTestTypesTgzWithFallbackAndConfiguration(), AllFeaturesEnabled); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' with { +extension 'br:example.azurecr.io/providers/foo:1.2.3' with { namespace: 'ThirdPartyNamespace' config: 'Some path to config file' context: 'Some ThirdParty context' @@ -389,7 +389,7 @@ public async Task Missing_configuration_property_throws_errors() // Missing the required configuration property: namespace var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' with { +extension 'br:example.azurecr.io/providers/foo:1.2.3' with { config: 'Some path to config file' context: 'Some ThirdParty context' } @@ -415,7 +415,7 @@ public async Task Mispelled_required_configuration_property_throws_error() // Mispelled the required configuration property: namespace var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' with { +extension 'br:example.azurecr.io/providers/foo:1.2.3' with { namespac: 'ThirdPartyNamespace' config: 'Some path to config file' context: 'Some ThirdParty context' @@ -443,7 +443,7 @@ public async Task Mispelled_optional_configuration_property_throws_error() // Mispelled the optional configuration property: context var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' with { +extension 'br:example.azurecr.io/providers/foo:1.2.3' with { namespace: 'ThirdPartyNamespace' config: 'Some path to config file' contex: 'Some ThirdParty context' @@ -469,7 +469,7 @@ public async Task Warning_generated_and_fallback_type_type_accepted() var services = await ProviderTestHelper.GetServiceBuilderWithPublishedProvider(ThirdPartyTypeHelper.GetTestTypesTgzWithFallbackAndConfiguration(), AllFeaturesEnabled); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' with { +extension 'br:example.azurecr.io/providers/foo:1.2.3' with { namespace: 'ThirdPartyNamespace' config: 'Some path to config file' } @@ -495,7 +495,7 @@ public async Task Fallback_not_provided_in_json() var services = await ProviderTestHelper.GetServiceBuilderWithPublishedProvider(ThirdPartyTypeHelper.GetTestTypesTgz(), AllFeaturesEnabled); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider 'br:example.azurecr.io/providers/foo:1.2.3' +extension 'br:example.azurecr.io/providers/foo:1.2.3' resource test 'test@v1' = { bodyProp: 'fallback body' @@ -514,7 +514,7 @@ public async Task Provider_imports_can_be_defined_in_config() var fileSystem = new MockFileSystem(); var services = await ProviderTestHelper.GetServiceBuilderWithPublishedProvider(ThirdPartyTypeHelper.GetTestTypesTgz(), AllFeaturesEnabled, fileSystem); - // incorrect provider version - verify it returns an error + // incorrect extension version - verify it returns an error fileSystem.File.WriteAllText("/bicepconfig.json", """ { "providers": { @@ -527,7 +527,7 @@ public async Task Provider_imports_can_be_defined_in_config() } """); var result = await CompilationHelper.RestoreAndCompile(services, """ -provider foo +extension foo """); result.Should().NotGenerateATemplate(); @@ -535,7 +535,7 @@ provider foo ("BCP192", DiagnosticLevel.Error, """Unable to restore the artifact with reference "br:example.azurecr.io/providers/foo:1.2.4": The artifact does not exist in the registry.""") }); - // correct provider version + // correct extension version fileSystem.File.WriteAllText("/bicepconfig.json", """ { "providers": { @@ -548,7 +548,7 @@ provider foo } """); result = await CompilationHelper.RestoreAndCompile(services, """ -provider foo +extension foo resource fooRes 'fooType@v1' = { identifier: 'foo' @@ -560,7 +560,7 @@ provider foo result.Should().GenerateATemplate(); - // correct provider version, defined implicitly + // correct extension version, defined implicitly fileSystem.File.WriteAllText("/bicepconfig.json", """ { "providers": { diff --git a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs index f7afa1011b3..a33a92d5307 100644 --- a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs +++ b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs @@ -5738,7 +5738,7 @@ public void Test_Issue12347() .WithFeatureOverrides(new(TestContext, ExtensibilityEnabled: true)) .WithConfigurationPatch(x => x.WithAnalyzersConfiguration(x.Analyzers.SetValue("core.rules.use-recent-api-versions.level", "error"))), ("main.bicep", """ - provider kubernetes with { + extension kubernetes with { kubeConfig: 'config' namespace: '' } as k8s diff --git a/src/Bicep.Core.IntegrationTests/TypeSystem/Providers/ResourceTypeProviderFactoryTests.cs b/src/Bicep.Core.IntegrationTests/TypeSystem/Providers/ResourceTypeProviderFactoryTests.cs index fd62af9fbda..f336ed13d35 100644 --- a/src/Bicep.Core.IntegrationTests/TypeSystem/Providers/ResourceTypeProviderFactoryTests.cs +++ b/src/Bicep.Core.IntegrationTests/TypeSystem/Providers/ResourceTypeProviderFactoryTests.cs @@ -45,7 +45,7 @@ public async Task ProviderNameAndVersionAreUsedAsCacheKeys() ( "main.bicep", @$" - provider 'br:example.azurecr.io/test/provider/foo:1.2.3' as foo + extension 'br:example.azurecr.io/test/provider/foo:1.2.3' as foo module mod './mod.bicep' = {{ name: 'mod' @@ -56,7 +56,7 @@ public async Task ProviderNameAndVersionAreUsedAsCacheKeys() ( "mod.bicep", @$" - provider 'br:example.azurecr.io/test/provider/bar:1.2.3' as foo + extension 'br:example.azurecr.io/test/provider/bar:1.2.3' as foo " )); 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 bd9b016db53..f686c06c962 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 with { +extension 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 ee81ece2fdc..9353e085c89 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 as graph +extension 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 85a375b4166..8198c8f2cf5 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 +extension microsoftGraph resource resourceApp 'Microsoft.Graph/applications@beta' existing = { uniqueName: 'resourceApp' diff --git a/src/Bicep.Core.UnitTests/Configuration/ProviderConfigurationTests.cs b/src/Bicep.Core.UnitTests/Configuration/ProviderConfigurationTests.cs index a322b867445..4b07e5fa473 100644 --- a/src/Bicep.Core.UnitTests/Configuration/ProviderConfigurationTests.cs +++ b/src/Bicep.Core.UnitTests/Configuration/ProviderConfigurationTests.cs @@ -40,7 +40,7 @@ public void ProviderConfiguration_deserialization() provider.Should().BeNull(); errorBuilder!.Should().NotBeNull(); errorBuilder!.Should().HaveCode("BCP204"); - errorBuilder!.Should().HaveMessage($"Provider namespace \"unspecified\" is not recognized."); + errorBuilder!.Should().HaveMessage($"Extension \"unspecified\" is not recognized."); } [TestMethod] @@ -98,6 +98,6 @@ public void ProviderConfiguration_user_provided_configuration_overrides_default_ provider.Should().BeNull(); errorBuilder!.Should().NotBeNull(); errorBuilder!.Should().HaveCode("BCP204"); - errorBuilder!.Should().HaveMessage($"Provider namespace \"sys\" is not recognized."); + errorBuilder!.Should().HaveMessage($"Extension \"sys\" is not recognized."); } } diff --git a/src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs b/src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs index 7f3f9e53bd7..8b0be36d163 100644 --- a/src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs +++ b/src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs @@ -1219,9 +1219,9 @@ public ErrorDiagnostic UnknownModuleReferenceScheme(string badScheme, ImmutableA public ErrorDiagnostic ExpectedProviderSpecification() { var message = """ - Expected a provider specification string with a valid format at this location. Valid formats: - * "br:/:" - * "br/::" + Expected an extension specification string with a valid format at this location. Valid formats: + * "br:/:" + * "br/::" """; return new(TextSpan, "BCP201", message); } @@ -1229,27 +1229,27 @@ public ErrorDiagnostic ExpectedProviderSpecification() public ErrorDiagnostic ExpectedProviderAliasName() => new( TextSpan, "BCP202", - "Expected a provider alias name at this location."); + "Expected an extension alias name at this location."); public ErrorDiagnostic ProvidersAreDisabled() => new( TextSpan, "BCP203", - $@"Using provider statements requires enabling EXPERIMENTAL feature ""{nameof(ExperimentalFeaturesEnabled.Extensibility)}""."); + $@"Using extension declaration requires enabling EXPERIMENTAL feature ""{nameof(ExperimentalFeaturesEnabled.Extensibility)}""."); public ErrorDiagnostic UnrecognizedProvider(string identifier) => new( TextSpan, "BCP204", - $"Provider namespace \"{identifier}\" is not recognized."); + $"Extension \"{identifier}\" is not recognized."); public ErrorDiagnostic ProviderDoesNotSupportConfiguration(string identifier) => new( TextSpan, "BCP205", - $"Provider namespace \"{identifier}\" does not support configuration."); + $"Extension \"{identifier}\" does not support configuration."); public ErrorDiagnostic ProviderRequiresConfiguration(string identifier) => new( TextSpan, "BCP206", - $"Provider namespace \"{identifier}\" requires configuration, but none was provided."); + $"Extension \"{identifier}\" requires configuration, but none was provided."); public ErrorDiagnostic NamespaceMultipleDeclarations(string identifier) => new( TextSpan, @@ -2076,19 +2076,19 @@ public ErrorDiagnostic RuntimeValueNotAllowedInFunctionDeclaration(string? acces $"Artifacts of type: \"{artifactType}\" are not supported." ); - public FixableDiagnostic ProviderDeclarationViaImportKeywordIsDeprecated(ProviderDeclarationSyntax syntax) + public FixableDiagnostic ExtensionDeclarationKeywordIsDeprecated(ProviderDeclarationSyntax syntax) { var codeFix = new CodeFix( - "Replace the import with the provider keyword", + $"Replace the {syntax.Keyword.Text} keyword with the extension keyword", true, CodeFixKind.QuickFix, - new CodeReplacement(syntax.Keyword.Span, LanguageConstants.ProviderKeyword)); + new CodeReplacement(syntax.Keyword.Span, LanguageConstants.ExtensionKeyword)); return new FixableDiagnostic( TextSpan, DiagnosticLevel.Warning, "BCP381", - $"Declaring provider namespaces with the \"import\" keyword has been deprecated. Please use the \"provider\" keyword instead.", + @$"Declaring extension with the ""{syntax.Keyword.Text}"" keyword has been deprecated. Please use the ""extension"" keyword instead. Please see https://github.com/Azure/bicep/issues/14374 for more information.", documentationUri: null, DiagnosticStyling.Default, codeFix); diff --git a/src/Bicep.Core/LanguageConstants.cs b/src/Bicep.Core/LanguageConstants.cs index 1a3b7c6c8f3..45bcb427ae5 100644 --- a/src/Bicep.Core/LanguageConstants.cs +++ b/src/Bicep.Core/LanguageConstants.cs @@ -72,6 +72,7 @@ public static class LanguageConstants public const string ExistingKeyword = "existing"; public const string ImportKeyword = "import"; public const string ProviderKeyword = "provider"; + public const string ExtensionKeyword = "extension"; public const string AssertKeyword = "assert"; public const string WithKeyword = "with"; public const string AsKeyword = "as"; diff --git a/src/Bicep.Core/Parsing/Parser.cs b/src/Bicep.Core/Parsing/Parser.cs index 79c216a9faa..fb90015190f 100644 --- a/src/Bicep.Core/Parsing/Parser.cs +++ b/src/Bicep.Core/Parsing/Parser.cs @@ -64,7 +64,8 @@ protected override SyntaxBase Declaration(params string[] expectedKeywords) => LanguageConstants.ModuleKeyword => this.ModuleDeclaration(leadingNodes), LanguageConstants.TestKeyword => this.TestDeclaration(leadingNodes), LanguageConstants.ImportKeyword => this.ImportDeclaration(leadingNodes), - LanguageConstants.ProviderKeyword => this.ProviderImportDeclaration(ExpectKeyword(LanguageConstants.ProviderKeyword), leadingNodes), + LanguageConstants.ProviderKeyword or + LanguageConstants.ExtensionKeyword => this.ExtensionDeclaration(ExpectKeyword(current.Text), leadingNodes), LanguageConstants.AssertKeyword => this.AssertDeclaration(leadingNodes), _ => leadingNodes.Length > 0 ? new MissingDeclarationSyntax(leadingNodes) @@ -275,12 +276,12 @@ private SyntaxBase ImportDeclaration(IEnumerable leadingNodes) return reader.Peek().Type switch { TokenType.StringLeftPiece or - TokenType.StringComplete => ProviderImportDeclaration(keyword, leadingNodes), + TokenType.StringComplete => ExtensionDeclaration(keyword, leadingNodes), _ => CompileTimeImportDeclaration(keyword, leadingNodes), }; } - private ProviderDeclarationSyntax ProviderImportDeclaration(Token keyword, IEnumerable leadingNodes) + private ProviderDeclarationSyntax ExtensionDeclaration(Token keyword, IEnumerable leadingNodes) { var providerSpecificationSyntax = reader.Peek().Type switch { @@ -299,7 +300,7 @@ TokenType.EndOfFile or TokenType.NewLine => this.SkipEmpty(), TokenType.Identifier when current.Text == LanguageConstants.AsKeyword => this.SkipEmpty(), - _ => this.WithRecovery(() => this.ProviderWithClause(), GetSuppressionFlag(providerSpecificationSyntax), TokenType.NewLine), + _ => this.WithRecovery(() => this.ExtensionWithClause(), GetSuppressionFlag(providerSpecificationSyntax), TokenType.NewLine), }; current = this.reader.Peek(); @@ -308,13 +309,13 @@ TokenType.EndOfFile or TokenType.EndOfFile or TokenType.NewLine => this.SkipEmpty(), - _ => this.WithRecovery(() => this.ProviderAsClause(), GetSuppressionFlag(withClause), TokenType.NewLine), + _ => this.WithRecovery(() => this.ExtensionAsClause(), GetSuppressionFlag(withClause), TokenType.NewLine), }; return new(leadingNodes, keyword, providerSpecificationSyntax, withClause, asClause); } - private ProviderWithClauseSyntax ProviderWithClause() + private ProviderWithClauseSyntax ExtensionWithClause() { var keyword = this.ExpectKeyword(LanguageConstants.WithKeyword, b => b.ExpectedWithOrAsKeywordOrNewLine()); var config = this.WithRecovery(() => this.Object(ExpressionFlags.AllowComplexLiterals), RecoveryFlags.None, TokenType.NewLine); @@ -322,7 +323,7 @@ private ProviderWithClauseSyntax ProviderWithClause() return new(keyword, config); } - private AliasAsClauseSyntax ProviderAsClause() + private AliasAsClauseSyntax ExtensionAsClause() { var keyword = this.ExpectKeyword(LanguageConstants.AsKeyword, b => b.ExpectedWithOrAsKeywordOrNewLine()); var modifier = this.IdentifierWithRecovery(b => b.ExpectedProviderAliasName(), RecoveryFlags.None, TokenType.NewLine); diff --git a/src/Bicep.Core/Syntax/ProviderDeclarationSyntax.cs b/src/Bicep.Core/Syntax/ProviderDeclarationSyntax.cs index c72f9e8df15..2941b577f79 100644 --- a/src/Bicep.Core/Syntax/ProviderDeclarationSyntax.cs +++ b/src/Bicep.Core/Syntax/ProviderDeclarationSyntax.cs @@ -13,7 +13,7 @@ public class ProviderDeclarationSyntax : StatementSyntax, ITopLevelDeclarationSy public ProviderDeclarationSyntax(IEnumerable leadingNodes, Token keyword, SyntaxBase specificationString, SyntaxBase withClause, SyntaxBase asClause) : base(leadingNodes) { - AssertKeyword(keyword, nameof(keyword), LanguageConstants.ImportKeyword, LanguageConstants.ProviderKeyword); + AssertKeyword(keyword, nameof(keyword), LanguageConstants.ImportKeyword, LanguageConstants.ProviderKeyword, LanguageConstants.ExtensionKeyword); AssertSyntaxType(specificationString, nameof(specificationString), typeof(StringSyntax), typeof(SkippedTriviaSyntax), typeof(IdentifierSyntax)); this.Keyword = keyword; diff --git a/src/Bicep.Core/TypeSystem/TypeAssignmentVisitor.cs b/src/Bicep.Core/TypeSystem/TypeAssignmentVisitor.cs index be2e389d60e..02e1fcf726e 100644 --- a/src/Bicep.Core/TypeSystem/TypeAssignmentVisitor.cs +++ b/src/Bicep.Core/TypeSystem/TypeAssignmentVisitor.cs @@ -880,9 +880,10 @@ public override void VisitProviderDeclarationSyntax(ProviderDeclarationSyntax sy return ErrorType.Empty(); } - if (syntax.Keyword.Text.Equals(LanguageConstants.ImportKeyword)) + if (syntax.Keyword.IsKeyword(LanguageConstants.ImportKeyword) || + syntax.Keyword.IsKeyword(LanguageConstants.ProviderKeyword)) { - diagnostics.Write(syntax.Keyword, x => x.ProviderDeclarationViaImportKeywordIsDeprecated(syntax)); + diagnostics.Write(syntax.Keyword, x => x.ExtensionDeclarationKeywordIsDeprecated(syntax)); } if (namespaceSymbol.DeclaredType is not NamespaceType namespaceType) diff --git a/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs b/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs index 7cd221fa8a8..8f82d469e92 100644 --- a/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs @@ -555,10 +555,19 @@ public async Task Provider_codefix_works() imp|ort 'br:example.azurecr.io/test/radius:1.0.0' ", server: server); - var updatedFile = ApplyCodeAction(bicepFile, codeActions.Single(x => x.Title.StartsWith("Replace the import with the provider keyword"))); + var updatedFile = ApplyCodeAction(bicepFile, codeActions.Single(x => x.Title.StartsWith("Replace the import keyword with the extension keyword"))); updatedFile.Should().HaveSourceText(@" -provider 'br:example.azurecr.io/test/radius:1.0.0' +extension 'br:example.azurecr.io/test/radius:1.0.0' "); + +// (codeActions, bicepFile) = await RunSyntaxTest(@" +//pro|vider 'br:example.azurecr.io/test/radius:1.0.0' +//", server: server); + +// updatedFile = ApplyCodeAction(bicepFile, codeActions.Single(x => x.Title.StartsWith("Replace the provider keyword with the extension keyword"))); +// updatedFile.Should().HaveSourceText(@" +//extension 'br:example.azurecr.io/test/radius:1.0.0' +//"); } [DataRow("var|")] From 70ac99d94dd063727da13150189ddcf29d031f8e Mon Sep 17 00:00:00 2001 From: Shenglong Li Date: Thu, 20 Jun 2024 20:17:50 -0700 Subject: [PATCH 2/3] Update keyword --- src/Bicep.Cli.E2eTests/src/examples/local-deploy/main.bicep | 2 +- src/Bicep.Cli.E2eTests/src/examples/providers.ff/main.bicep | 2 +- src/Bicep.Cli.E2eTests/src/examples/providers.prod/main.bicep | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bicep.Cli.E2eTests/src/examples/local-deploy/main.bicep b/src/Bicep.Cli.E2eTests/src/examples/local-deploy/main.bicep index e18231ea610..1ee5894acc2 100644 --- a/src/Bicep.Cli.E2eTests/src/examples/local-deploy/main.bicep +++ b/src/Bicep.Cli.E2eTests/src/examples/local-deploy/main.bicep @@ -1,4 +1,4 @@ -provider '../../temp/local-deploy/provider.tgz' +extension '../../temp/local-deploy/provider.tgz' param payload string diff --git a/src/Bicep.Cli.E2eTests/src/examples/providers.ff/main.bicep b/src/Bicep.Cli.E2eTests/src/examples/providers.ff/main.bicep index 12381c51f28..dd0da571db9 100644 --- a/src/Bicep.Cli.E2eTests/src/examples/providers.ff/main.bicep +++ b/src/Bicep.Cli.E2eTests/src/examples/providers.ff/main.bicep @@ -1,4 +1,4 @@ -provider '$TARGET_REFERENCE' +extension '$TARGET_REFERENCE' resource dadJoke 'request@v1' = { uri: 'https://icanhazdadjoke.com' diff --git a/src/Bicep.Cli.E2eTests/src/examples/providers.prod/main.bicep b/src/Bicep.Cli.E2eTests/src/examples/providers.prod/main.bicep index 12381c51f28..dd0da571db9 100644 --- a/src/Bicep.Cli.E2eTests/src/examples/providers.prod/main.bicep +++ b/src/Bicep.Cli.E2eTests/src/examples/providers.prod/main.bicep @@ -1,4 +1,4 @@ -provider '$TARGET_REFERENCE' +extension '$TARGET_REFERENCE' resource dadJoke 'request@v1' = { uri: 'https://icanhazdadjoke.com' From ce75a9cca0e0f0b94f128529f783b33027c4394d Mon Sep 17 00:00:00 2001 From: Shenglong Li Date: Mon, 24 Jun 2024 10:49:56 -0700 Subject: [PATCH 3/3] Uncomment a test case --- .../CodeActionTests.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs b/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs index 8f82d469e92..d77ede97a71 100644 --- a/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/CodeActionTests.cs @@ -560,14 +560,14 @@ public async Task Provider_codefix_works() extension 'br:example.azurecr.io/test/radius:1.0.0' "); -// (codeActions, bicepFile) = await RunSyntaxTest(@" -//pro|vider 'br:example.azurecr.io/test/radius:1.0.0' -//", server: server); - -// updatedFile = ApplyCodeAction(bicepFile, codeActions.Single(x => x.Title.StartsWith("Replace the provider keyword with the extension keyword"))); -// updatedFile.Should().HaveSourceText(@" -//extension 'br:example.azurecr.io/test/radius:1.0.0' -//"); + (codeActions, bicepFile) = await RunSyntaxTest(@" +pro|vider 'br:example.azurecr.io/test/radius:1.0.0' +", server: server); + + updatedFile = ApplyCodeAction(bicepFile, codeActions.Single(x => x.Title.StartsWith("Replace the provider keyword with the extension keyword"))); + updatedFile.Should().HaveSourceText(@" +extension 'br:example.azurecr.io/test/radius:1.0.0' +"); } [DataRow("var|")]