From b1bf95824d7568e3a00eb7db498f8f3789eefa4e Mon Sep 17 00:00:00 2001 From: Anthony Martin <38542602+anthony-c-martin@users.noreply.github.com> Date: Tue, 30 Jan 2024 20:09:03 -0500 Subject: [PATCH 1/2] Remove experimental feature for user defined functions --- docs/experimental-features.md | 3 - .../CompileTimeImportTests.cs | 77 ++----------------- .../EvaluationTests.cs | 3 +- .../LambdaTests.cs | 3 +- .../ScenarioTests.cs | 25 ++---- .../UserDefinedFunctionTests.cs | 31 ++------ .../baselines/Completions/declarations.json | 18 +++++ .../baselines/Functions_LF/bicepconfig.json | 5 -- .../baselines/Imports_LF/bicepconfig.json | 5 -- .../InvalidFunctions_LF/bicepconfig.json | 5 -- .../Imports/bicepconfig.bicep | 6 +- .../Imports/bicepconfig.json | 5 -- .../baselines_bicepparam/Imports/foo.json | 5 ++ .../ConfigurationManagerTests.cs | 4 - .../Features/FeatureProviderOverrides.cs | 3 - .../Features/OverriddenFeatureProvider.cs | 2 - .../ExperimentalFeaturesEnabled.cs | 1 - src/Bicep.Core/CoreResources.Designer.cs | 9 --- src/Bicep.Core/CoreResources.resx | 3 - .../Diagnostics/DiagnosticBuilder.cs | 5 -- .../Emit/EmitLimitationCalculator.cs | 12 --- src/Bicep.Core/Features/FeatureProvider.cs | 2 - src/Bicep.Core/Features/IFeatureProvider.cs | 3 - .../Semantics/DeclarationVisitor.cs | 7 +- .../TypeSystem/TypeAssignmentVisitor.cs | 5 -- .../CompletionTests.cs | 34 ++------ .../DefinitionTests.cs | 2 - .../SignatureHelpTests.cs | 4 +- .../Completions/BicepCompletionProvider.cs | 13 ++-- .../test/baselines/bicepconfig.json | 5 -- src/monarch/test/baselines/bicepconfig.json | 5 -- src/textmate/test/baselines/bicepconfig.json | 5 -- .../schemas/bicepconfig.schema.json | 4 - 33 files changed, 64 insertions(+), 255 deletions(-) delete mode 100644 src/Bicep.Core.Samples/Files/baselines/Functions_LF/bicepconfig.json delete mode 100644 src/Bicep.Core.Samples/Files/baselines/Imports_LF/bicepconfig.json delete mode 100644 src/Bicep.Core.Samples/Files/baselines/InvalidFunctions_LF/bicepconfig.json delete mode 100644 src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/bicepconfig.json create mode 100644 src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/foo.json delete mode 100644 src/highlightjs/test/baselines/bicepconfig.json delete mode 100644 src/monarch/test/baselines/bicepconfig.json delete mode 100644 src/textmate/test/baselines/bicepconfig.json diff --git a/docs/experimental-features.md b/docs/experimental-features.md index 7ac5cb5631a..d9578ea429c 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -42,9 +42,6 @@ Allows the ARM template layer to use a new schema to represent resources as an o ### `testFramework` Should be enabled in tandem with `assertions` experimental feature flag for expected functionality. Allows you to author client-side, offline unit-test test blocks that reference Bicep files and mock deployment parameters in a separate `test.bicep` file using the new `test` keyword. Test blocks can be run with the command *bicep test * which runs all `assert` statements in the Bicep files referenced by the test blocks. For more information, see [Bicep Experimental Test Framework](https://github.com/Azure/bicep/issues/11967). -### `userDefinedFunctions` -Allows you to define your own custom functions. See [User-defined functions in Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/user-defined-functions). - ## Other experimental functionality ### `publish-provider` CLI Command diff --git a/src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs b/src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs index 6bf5fd51a48..6cccb9afe6e 100644 --- a/src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs +++ b/src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs @@ -20,9 +20,6 @@ namespace Bicep.Core.IntegrationTests; [TestClass] public class CompileTimeImportTests { - private ServiceBuilder ServicesWithUserDefinedFunctions => new ServiceBuilder() - .WithFeatureOverrides(new(TestContext, UserDefinedFunctionsEnabled: true)); - [NotNull] public TestContext? TestContext { get; set; } @@ -194,7 +191,7 @@ public void Imported_variable_symbols_should_have_declarations_injected_into_com [TestMethod] public void Imported_function_symbols_should_have_declarations_injected_into_compiled_template() { - var result = CompilationHelper.Compile(ServicesWithUserDefinedFunctions, + var result = CompilationHelper.Compile( ("main.bicep", """ import {greet} from 'mod.bicep' """), @@ -234,64 +231,6 @@ func greet(name string) string => 'Hi, ${name}!' """)); } - [TestMethod] - public void Importing_functions_should_be_blocked_if_user_defined_functions_feature_not_enabled() - { - var featureProviderFactory = StrictMock.Of(); - var defaultFeatures = new FeatureProvider(IConfigurationManager.GetBuiltInConfiguration()); - featureProviderFactory - .Setup(m => m.GetFeatureProvider(It.Is(uri => uri.AbsolutePath.EndsWith("main.bicep")))) - .Returns(defaultFeatures); - featureProviderFactory - .Setup(m => m.GetFeatureProvider(It.Is(uri => uri.AbsolutePath.EndsWith("mod.bicep")))) - .Returns(new OverriddenFeatureProvider(defaultFeatures, new(UserDefinedFunctionsEnabled: true))); - - var result = CompilationHelper.Compile(new ServiceBuilder().WithFeatureProviderFactory(featureProviderFactory.Object), - ("main.bicep", """ - import {greet} from 'mod.bicep' - """), - ("mod.bicep", """ - @export() - @description('Say hi to someone') - func greet(name string) string => 'Hi, ${name}!' - """)); - - result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] - { - ("BCP343", DiagnosticLevel.Error, $@"Using a func declaration statement requires enabling EXPERIMENTAL feature ""{nameof(ExperimentalFeaturesEnabled.UserDefinedFunctions)}"".") - }); - } - - [TestMethod] - public void Calling_methods_on_wildcard_imports_should_be_blocked_if_user_defined_functions_feature_not_enabled() - { - var featureProviderFactory = StrictMock.Of(); - var defaultFeatures = new FeatureProvider(IConfigurationManager.GetBuiltInConfiguration()); - featureProviderFactory - .Setup(m => m.GetFeatureProvider(It.Is(uri => uri.AbsolutePath.EndsWith("main.bicep")))) - .Returns(defaultFeatures); - featureProviderFactory - .Setup(m => m.GetFeatureProvider(It.Is(uri => uri.AbsolutePath.EndsWith("mod.bicep")))) - .Returns(new OverriddenFeatureProvider(defaultFeatures, new(UserDefinedFunctionsEnabled: true))); - - var result = CompilationHelper.Compile(new ServiceBuilder().WithFeatureProviderFactory(featureProviderFactory.Object), - ("main.bicep", """ - import * as mod from 'mod.bicep' - - output greeting string = mod.greet('friend') - """), - ("mod.bicep", """ - @export() - @description('Say hi to someone') - func greet(name string) string => 'Hi, ${name}!' - """)); - - result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] - { - ("BCP343", DiagnosticLevel.Error, $@"Using a func declaration statement requires enabling EXPERIMENTAL feature ""{nameof(ExperimentalFeaturesEnabled.UserDefinedFunctions)}"".") - }); - } - [TestMethod] public void Type_symbols_imported_from_ARM_json_should_have_declarations_injected_into_compiled_template() { @@ -467,7 +406,7 @@ public void Variable_symbols_imported_from_ARM_json_with_wildcard_syntax_should_ [TestMethod] public void Function_symbols_imported_from_ARM_json_should_have_declarations_injected_into_compiled_template() { - var result = CompilationHelper.Compile(ServicesWithUserDefinedFunctions, + var result = CompilationHelper.Compile( ("main.bicep", """ import {greet, 'ns.cow_say' as cowSay} from 'mod.json' """), @@ -686,7 +625,7 @@ public void Funky_ARM_allowedValues_survive_symbol_import_and_injection() [TestMethod] public void Symbols_imported_via_wildcard_should_have_declarations_injected_into_compiled_template() { - var result = CompilationHelper.Compile(ServicesWithUserDefinedFunctions, + var result = CompilationHelper.Compile( ("main.bicep", """ import * as foo from 'mod.bicep' """), @@ -1009,7 +948,7 @@ public void Imported_variable_symbols_with_a_lengthy_reference_chain_should_have [TestMethod] public void Imported_function_symbols_with_a_lengthy_reference_chain_should_have_declarations_injected_into_compiled_template() { - var result = CompilationHelper.Compile(ServicesWithUserDefinedFunctions, + var result = CompilationHelper.Compile( ("main.bicep", """ import {foo} from 'mod.bicep' @@ -1835,7 +1774,7 @@ public void Test_Issue12396() [TestMethod] public void Symbolic_name_target_is_used_when_function_import_closure_includes_a_user_defined_type() { - var result = CompilationHelper.Compile(ServicesWithUserDefinedFunctions, + var result = CompilationHelper.Compile( ("main.bicep", """ import { capitalizer } from 'function.bicep' """), @@ -1956,7 +1895,7 @@ public void Imported_variable_symbols_that_use_compile_time_functions_should_hav [TestMethod] public void User_defined_function_calls_parameters_to_other_user_defined_function_calls_are_migrated_during_import() { - var result = CompilationHelper.Compile(ServicesWithUserDefinedFunctions, + var result = CompilationHelper.Compile( ("main.bicep", """ import {getSubnetNumber, isWindows} from 'types.bicep' @@ -2042,7 +1981,7 @@ public void Imported_objects_can_be_used_in_discriminated_object_type_narrowing( [TestMethod] public void LanguageVersion_2_should_be_used_if_types_imported_via_wildcard() { - var result = CompilationHelper.Compile(ServicesWithUserDefinedFunctions, + var result = CompilationHelper.Compile( ("main.bicep", """ import * as types from 'types.bicep' """), @@ -2080,7 +2019,7 @@ INVALID FILE [TestMethod] public void LanguageVersion_2_should_be_used_if_types_imported_via_closure() { - var result = CompilationHelper.Compile(ServicesWithUserDefinedFunctions, + var result = CompilationHelper.Compile( ("main.bicep", """ import {a} from 'shared.bicep' """), diff --git a/src/Bicep.Core.IntegrationTests/EvaluationTests.cs b/src/Bicep.Core.IntegrationTests/EvaluationTests.cs index c77247cf5a9..1bec6fdc73e 100644 --- a/src/Bicep.Core.IntegrationTests/EvaluationTests.cs +++ b/src/Bicep.Core.IntegrationTests/EvaluationTests.cs @@ -1134,7 +1134,6 @@ param foo string? [TestMethod] public void Functions_are_evaluated_correctly() { - var services = new ServiceBuilder().WithFeatureOverrides(new(TestContext, UserDefinedFunctionsEnabled: true)); var bicepFile = @" // yeah, this is a bit pointless func joinWithSpace(values string[]) string => join(values, ' ') @@ -1152,7 +1151,7 @@ func replaceMultiple(value string, input object) string => reduce( }) "; - var (template, _, _) = CompilationHelper.Compile(services, bicepFile); + var (template, _, _) = CompilationHelper.Compile(bicepFile); using (new AssertionScope()) { diff --git a/src/Bicep.Core.IntegrationTests/LambdaTests.cs b/src/Bicep.Core.IntegrationTests/LambdaTests.cs index 81d20114653..29829e8db8f 100644 --- a/src/Bicep.Core.IntegrationTests/LambdaTests.cs +++ b/src/Bicep.Core.IntegrationTests/LambdaTests.cs @@ -362,8 +362,7 @@ public void DeployTimeConstant_detection_works_with_lambdas() [TestMethod] public void Function_recursion_is_blocked() { - var services = new ServiceBuilder().WithFeatureOverrides(BicepTestConstants.FeatureOverrides with { UserDefinedFunctionsEnabled = true }); - var result = CompilationHelper.Compile(services, @" + var result = CompilationHelper.Compile(@" func recursive() string => recursive() func recursiveA() string => recursiveB() diff --git a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs index e2343ddb2e0..1d52298ef25 100644 --- a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs +++ b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs @@ -4798,9 +4798,7 @@ public void Lambda_variable_declarations_should_overwrite_globally_scoped_functi [TestMethod] public void Typed_lambda_variable_declarations_should_overwrite_globally_scoped_functions() { - var services = new ServiceBuilder().WithFeatureOverrides(new(UserDefinedFunctionsEnabled: true)); - - var result = CompilationHelper.Compile(services, @" + var result = CompilationHelper.Compile(@" func foo(resourceGroup string) string => resourceGroup('test') "); @@ -5424,7 +5422,6 @@ public void Test_Issue12912() { var result = CompilationHelper.Compile( - Services.WithFeatureOverrides(new(UserDefinedFunctionsEnabled: true)), ("main.bicep", """ func test() object => loadJsonContent('./repro-data.json') func test2() string => loadTextContent('./repro-data.json') @@ -5449,7 +5446,6 @@ public void Test_Issue12698() { var result = CompilationHelper.Compile( - Services.WithFeatureOverrides(new(UserDefinedFunctionsEnabled: true)), ("main.bicep", """ import { MyFunction } from 'export.bicep' @@ -5492,17 +5488,17 @@ param two bool output bothTrue bool = one && two """), ("bicepconfig.bicep", """ -var json = loadJsonContent('bicepconfig.json') +var json = loadJsonContent('foo.json') func testFunction(b bool) bool => b @export() -var directExport = json.experimentalFeaturesEnabled.userDefinedFunctions +var directExport = json.bar.baz @export() -var functionExport = testFunction(json.experimentalFeaturesEnabled.userDefinedFunctions) +var functionExport = testFunction(json.bar.baz) """), - ("bicepconfig.json", """ + ("foo.json", """ { - "experimentalFeaturesEnabled": { - "userDefinedFunctions": true + "bar": { + "baz": true } } """)); @@ -5650,13 +5646,6 @@ func greetMultiple(names string[]) string[] => map(names, name => greet(name)) ("main.bicep", """ param foo string param foo2 string[] -"""), - ("bicepconfig.json", """ -{ - "experimentalFeaturesEnabled": { - "userDefinedFunctions": true - } -} """)); result.Should().NotHaveAnyDiagnostics(); diff --git a/src/Bicep.Core.IntegrationTests/UserDefinedFunctionTests.cs b/src/Bicep.Core.IntegrationTests/UserDefinedFunctionTests.cs index acb8bde22e4..c6f8128c4b6 100644 --- a/src/Bicep.Core.IntegrationTests/UserDefinedFunctionTests.cs +++ b/src/Bicep.Core.IntegrationTests/UserDefinedFunctionTests.cs @@ -12,15 +12,12 @@ namespace Bicep.Core.IntegrationTests; [TestClass] public class UserDefinedFunctionTests { - private ServiceBuilder Services => new ServiceBuilder() - .WithFeatureOverrides(new(TestContext, UserDefinedFunctionsEnabled: true)); - [NotNull] public TestContext? TestContext { get; set; } [TestMethod] public void User_defined_functions_basic_case() { - var result = CompilationHelper.Compile(Services, @" + var result = CompilationHelper.Compile(@" func buildUrl(https bool, hostname string, path string) string => '${https ? 'https' : 'http'}://${hostname}${empty(path) ? '' : '/${path}'}' output foo string = buildUrl(true, 'google.com', 'search') @@ -35,7 +32,7 @@ func buildUrl(https bool, hostname string, path string) string => '${https ? 'ht [TestMethod] public void Outer_scope_symbolic_references_are_blocked() { - var result = CompilationHelper.Compile(Services, @" + var result = CompilationHelper.Compile(@" param foo string var bar = 'abc' func getBaz() string => 'baz' @@ -52,7 +49,7 @@ func testFunc(baz string) string => '${foo}-${bar}-${baz}-${getBaz()}' [TestMethod] public void Functions_can_have_descriptions_applied() { - var result = CompilationHelper.Compile(Services, @" + var result = CompilationHelper.Compile(@" @description('Returns foo') func returnFoo() string => 'foo' @@ -68,15 +65,13 @@ func returnFoo() string => 'foo' [TestMethod] public void User_defined_functions_support_custom_types() { - var services = new ServiceBuilder().WithFeatureOverrides(new(UserDefinedFunctionsEnabled: true)); - - var result = CompilationHelper.Compile(services, @" + var result = CompilationHelper.Compile(@" func getAOrB(aOrB ('a' | 'b')) bool => (aOrB == 'a') "); result.Should().NotHaveAnyDiagnostics(); - result = CompilationHelper.Compile(services, @" + result = CompilationHelper.Compile(@" func getAOrB(aOrB bool) ('a' | 'b') => aOrB ? 'a' : 'b' "); @@ -86,7 +81,7 @@ func getAOrB(aOrB bool) ('a' | 'b') => aOrB ? 'a' : 'b' [TestMethod] public void User_defined_functions_unsupported_runtime_functions() { - var result = CompilationHelper.Compile(Services, @" + var result = CompilationHelper.Compile(@" func useRuntimeFunction() string => reference('foo').bar "); @@ -94,18 +89,4 @@ func useRuntimeFunction() string => reference('foo').bar ("BCP341", DiagnosticLevel.Error, "This expression is being used inside a function declaration, which requires a value that can be calculated at the start of the deployment."), }); } - - [TestMethod] - public void User_defined_functions_requires_experimental_feature_enabled() - { - var services = new ServiceBuilder().WithFeatureOverrides(new()); - - var result = CompilationHelper.Compile(services, @" -func useRuntimeFunction() string => 'test' -"); - - result.Should().HaveDiagnostics(new[] { - ("BCP343", DiagnosticLevel.Error, "Using a func declaration statement requires enabling EXPERIMENTAL feature \"UserDefinedFunctions\"."), - }); - } } diff --git a/src/Bicep.Core.Samples/Files/baselines/Completions/declarations.json b/src/Bicep.Core.Samples/Files/baselines/Completions/declarations.json index ade548051b5..8d4a92f7e93 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Completions/declarations.json +++ b/src/Bicep.Core.Samples/Files/baselines/Completions/declarations.json @@ -1,4 +1,22 @@ [ + { + "label": "func", + "kind": "snippet", + "detail": "Function declaration", + "documentation": { + "kind": "markdown", + "value": "```bicep\nfunc name() outputType => \n``` \n" + }, + "deprecated": false, + "preselect": false, + "sortText": "2_func", + "insertTextFormat": "snippet", + "insertTextMode": "adjustIndentation", + "textEdit": { + "range": {}, + "newText": "func ${1:name}() ${2:outputType} => $0" + } + }, { "label": "import", "kind": "keyword", diff --git a/src/Bicep.Core.Samples/Files/baselines/Functions_LF/bicepconfig.json b/src/Bicep.Core.Samples/Files/baselines/Functions_LF/bicepconfig.json deleted file mode 100644 index 111be40be4a..00000000000 --- a/src/Bicep.Core.Samples/Files/baselines/Functions_LF/bicepconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "experimentalFeaturesEnabled": { - "userDefinedFunctions": true - } -} \ No newline at end of file diff --git a/src/Bicep.Core.Samples/Files/baselines/Imports_LF/bicepconfig.json b/src/Bicep.Core.Samples/Files/baselines/Imports_LF/bicepconfig.json deleted file mode 100644 index e9860dc4b44..00000000000 --- a/src/Bicep.Core.Samples/Files/baselines/Imports_LF/bicepconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "experimentalFeaturesEnabled": { - "userDefinedFunctions": true - } -} diff --git a/src/Bicep.Core.Samples/Files/baselines/InvalidFunctions_LF/bicepconfig.json b/src/Bicep.Core.Samples/Files/baselines/InvalidFunctions_LF/bicepconfig.json deleted file mode 100644 index e9860dc4b44..00000000000 --- a/src/Bicep.Core.Samples/Files/baselines/InvalidFunctions_LF/bicepconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "experimentalFeaturesEnabled": { - "userDefinedFunctions": true - } -} diff --git a/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/bicepconfig.bicep b/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/bicepconfig.bicep index 80a623b2f45..9249622cc0b 100644 --- a/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/bicepconfig.bicep +++ b/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/bicepconfig.bicep @@ -1,6 +1,6 @@ -var json = loadJsonContent('bicepconfig.json') +var json = loadJsonContent('foo.json') func testFunction(b bool) bool => b @export() -var directExport = json.experimentalFeaturesEnabled.userDefinedFunctions +var directExport = json.bar.baz @export() -var functionExport = testFunction(json.experimentalFeaturesEnabled.userDefinedFunctions) +var functionExport = testFunction(json.bar.baz) diff --git a/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/bicepconfig.json b/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/bicepconfig.json deleted file mode 100644 index f619935d3e0..00000000000 --- a/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/bicepconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "experimentalFeaturesEnabled": { - "userDefinedFunctions": true - } -} \ No newline at end of file diff --git a/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/foo.json b/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/foo.json new file mode 100644 index 00000000000..2e3276cc7e7 --- /dev/null +++ b/src/Bicep.Core.Samples/Files/baselines_bicepparam/Imports/foo.json @@ -0,0 +1,5 @@ +{ + "bar": { + "baz": true + } +} \ No newline at end of file diff --git a/src/Bicep.Core.UnitTests/Configuration/ConfigurationManagerTests.cs b/src/Bicep.Core.UnitTests/Configuration/ConfigurationManagerTests.cs index 7e8c5d3e802..76ab6fe6951 100644 --- a/src/Bicep.Core.UnitTests/Configuration/ConfigurationManagerTests.cs +++ b/src/Bicep.Core.UnitTests/Configuration/ConfigurationManagerTests.cs @@ -104,7 +104,6 @@ public void GetBuiltInConfiguration_NoParameter_ReturnsBuiltInConfigurationWithA "extensibility": false, "resourceTypedParamsAndOutputs": false, "sourceMapping": false, - "userDefinedFunctions": false, "legacyFormatter": false, "testFramework": false, "assertions": false, @@ -187,7 +186,6 @@ public void GetBuiltInConfiguration_DisableAllAnalyzers_ReturnsBuiltInConfigurat "extensibility": false, "resourceTypedParamsAndOutputs": false, "sourceMapping": false, - "userDefinedFunctions": false, "legacyFormatter": false, "testFramework": false, "assertions": false, @@ -295,7 +293,6 @@ public void GetBuiltInConfiguration_DisableAnalyzers_ReturnsBuiltInConfiguration "extensibility": false, "resourceTypedParamsAndOutputs": false, "sourceMapping": false, - "userDefinedFunctions": false, "legacyFormatter": false, "testFramework": false, "assertions": false, @@ -731,7 +728,6 @@ public void GetConfiguration_ValidCustomConfiguration_OverridesBuiltInConfigurat "extensibility": true, "resourceTypedParamsAndOutputs": false, "sourceMapping": false, - "userDefinedFunctions": false, "legacyFormatter": false, "testFramework": false, "assertions": false, diff --git a/src/Bicep.Core.UnitTests/Features/FeatureProviderOverrides.cs b/src/Bicep.Core.UnitTests/Features/FeatureProviderOverrides.cs index 0f1e418a086..e853a2e2acc 100644 --- a/src/Bicep.Core.UnitTests/Features/FeatureProviderOverrides.cs +++ b/src/Bicep.Core.UnitTests/Features/FeatureProviderOverrides.cs @@ -14,7 +14,6 @@ public record FeatureProviderOverrides( bool? AdvancedListComprehensionEnabled = default, bool? ResourceTypedParamsAndOutputsEnabled = default, bool? SourceMappingEnabled = default, - bool? UserDefinedFunctionsEnabled = default, bool? LegacyFormatterEnabled = default, bool? TestFrameworkEnabled = default, bool? AssertsEnabled = default, @@ -34,7 +33,6 @@ public FeatureProviderOverrides( bool? AdvancedListComprehensionEnabled = default, bool? ResourceTypedParamsAndOutputsEnabled = default, bool? SourceMappingEnabled = default, - bool? UserDefinedFunctionsEnabled = default, bool? LegacyFormatterEnabled = default, bool? TestFrameworkEnabled = default, bool? AssertsEnabled = default, @@ -53,7 +51,6 @@ public FeatureProviderOverrides( AdvancedListComprehensionEnabled, ResourceTypedParamsAndOutputsEnabled, SourceMappingEnabled, - UserDefinedFunctionsEnabled, LegacyFormatterEnabled, TestFrameworkEnabled, AssertsEnabled, diff --git a/src/Bicep.Core.UnitTests/Features/OverriddenFeatureProvider.cs b/src/Bicep.Core.UnitTests/Features/OverriddenFeatureProvider.cs index 7b5d730252d..a0ff4114466 100644 --- a/src/Bicep.Core.UnitTests/Features/OverriddenFeatureProvider.cs +++ b/src/Bicep.Core.UnitTests/Features/OverriddenFeatureProvider.cs @@ -28,8 +28,6 @@ public OverriddenFeatureProvider(IFeatureProvider features, FeatureProviderOverr public bool SourceMappingEnabled => overrides.SourceMappingEnabled ?? features.SourceMappingEnabled; - public bool UserDefinedFunctionsEnabled => overrides.UserDefinedFunctionsEnabled ?? features.UserDefinedFunctionsEnabled; - public bool LegacyFormatterEnabled => overrides.LegacyFormatterEnabled ?? features.LegacyFormatterEnabled; public bool TestFrameworkEnabled => overrides.TestFrameworkEnabled ?? features.TestFrameworkEnabled; diff --git a/src/Bicep.Core/Configuration/ExperimentalFeaturesEnabled.cs b/src/Bicep.Core/Configuration/ExperimentalFeaturesEnabled.cs index bb413e9e804..aca9db1441b 100644 --- a/src/Bicep.Core/Configuration/ExperimentalFeaturesEnabled.cs +++ b/src/Bicep.Core/Configuration/ExperimentalFeaturesEnabled.cs @@ -12,7 +12,6 @@ public record ExperimentalFeaturesEnabled( bool Extensibility, bool ResourceTypedParamsAndOutputs, bool SourceMapping, - bool UserDefinedFunctions, bool LegacyFormatter, bool TestFramework, bool Assertions, diff --git a/src/Bicep.Core/CoreResources.Designer.cs b/src/Bicep.Core/CoreResources.Designer.cs index 25fcd579c11..2a407f90609 100644 --- a/src/Bicep.Core/CoreResources.Designer.cs +++ b/src/Bicep.Core/CoreResources.Designer.cs @@ -276,15 +276,6 @@ internal static string ExperimentalFeatureNames_TestFramework { } } - /// - /// Looks up a localized string similar to User-defined functions. - /// - internal static string ExperimentalFeatureNames_UserDefinedFunctions { - get { - return ResourceManager.GetString("ExperimentalFeatureNames_UserDefinedFunctions", resourceCulture); - } - } - /// /// Looks up a localized string similar to Use string interpolation: {0}. /// diff --git a/src/Bicep.Core/CoreResources.resx b/src/Bicep.Core/CoreResources.resx index 0ebb48808ca..b7d1a6d43a2 100644 --- a/src/Bicep.Core/CoreResources.resx +++ b/src/Bicep.Core/CoreResources.resx @@ -470,9 +470,6 @@ Source mapping - - User-defined functions - Symbolic name code generation diff --git a/src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs b/src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs index c255242e8d6..72b1a42e1cb 100644 --- a/src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs +++ b/src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs @@ -1896,11 +1896,6 @@ public ErrorDiagnostic RuntimeValueNotAllowedInFunctionDeclaration(string? acces "BCP342", $"""User-defined types are not supported in user-defined function parameters or outputs."""); - public ErrorDiagnostic FuncDeclarationStatementsUnsupported() => new( - TextSpan, - "BCP343", - $@"Using a func declaration statement requires enabling EXPERIMENTAL feature ""{nameof(ExperimentalFeaturesEnabled.UserDefinedFunctions)}""."); - public ErrorDiagnostic ExpectedAssertIdentifier() => new( TextSpan, "BCP344", diff --git a/src/Bicep.Core/Emit/EmitLimitationCalculator.cs b/src/Bicep.Core/Emit/EmitLimitationCalculator.cs index 9ac9bfc69e5..d106ca906cc 100644 --- a/src/Bicep.Core/Emit/EmitLimitationCalculator.cs +++ b/src/Bicep.Core/Emit/EmitLimitationCalculator.cs @@ -48,7 +48,6 @@ public static EmitLimitationInfo Calculate(SemanticModel model) BlockModuleOutputResourcePropertyAccess(model, diagnostics); BlockSafeDereferenceOfModuleOrResourceCollectionMember(model, diagnostics); BlockCyclicAggregateTypeReferences(model, diagnostics); - BlockUserDefinedFunctionsWithoutExperimentalFeaure(model, diagnostics); BlockTestFrameworkWithoutExperimentalFeaure(model, diagnostics); BlockAssertsWithoutExperimentalFeatures(model, diagnostics); BlockNamesDistinguishedOnlyByCase(model, diagnostics); @@ -590,17 +589,6 @@ IEnumerable YieldSymbolAndUnprocessedPredecessors(DeclaredSymbol return referencesInValues.Keys.SelectMany(YieldSymbolAndUnprocessedPredecessors); } - private static void BlockUserDefinedFunctionsWithoutExperimentalFeaure(SemanticModel model, IDiagnosticWriter diagnostics) - { - foreach (var function in model.Root.FunctionDeclarations) - { - if (!model.Features.UserDefinedFunctionsEnabled) - { - diagnostics.Write(function.DeclaringFunction, x => x.FuncDeclarationStatementsUnsupported()); - } - } - } - private static void BlockTestFrameworkWithoutExperimentalFeaure(SemanticModel model, IDiagnosticWriter diagnostics) { foreach (var test in model.Root.TestDeclarations) diff --git a/src/Bicep.Core/Features/FeatureProvider.cs b/src/Bicep.Core/Features/FeatureProvider.cs index a348797609c..796fe8fba01 100644 --- a/src/Bicep.Core/Features/FeatureProvider.cs +++ b/src/Bicep.Core/Features/FeatureProvider.cs @@ -26,8 +26,6 @@ public FeatureProvider(RootConfiguration configuration) public bool SourceMappingEnabled => this.configuration.ExperimentalFeaturesEnabled.SourceMapping; - public bool UserDefinedFunctionsEnabled => configuration.ExperimentalFeaturesEnabled.UserDefinedFunctions; - public bool LegacyFormatterEnabled => configuration.ExperimentalFeaturesEnabled.LegacyFormatter; public bool TestFrameworkEnabled => this.configuration.ExperimentalFeaturesEnabled.TestFramework; diff --git a/src/Bicep.Core/Features/IFeatureProvider.cs b/src/Bicep.Core/Features/IFeatureProvider.cs index 4471b11e821..b4f76706e4f 100644 --- a/src/Bicep.Core/Features/IFeatureProvider.cs +++ b/src/Bicep.Core/Features/IFeatureProvider.cs @@ -17,8 +17,6 @@ public interface IFeatureProvider bool SourceMappingEnabled { get; } - bool UserDefinedFunctionsEnabled { get; } - bool DynamicTypeLoadingEnabled { get; } bool ProviderRegistryEnabled { get; } @@ -49,7 +47,6 @@ public interface IFeatureProvider (ExtensibilityEnabled, CoreResources.ExperimentalFeatureNames_Extensibility, true, true), (ResourceTypedParamsAndOutputsEnabled, CoreResources.ExperimentalFeatureNames_ResourceTypedParamsAndOutputs, true, false), (SourceMappingEnabled, CoreResources.ExperimentalFeatureNames_SourceMapping, true, false), - (UserDefinedFunctionsEnabled, CoreResources.ExperimentalFeatureNames_UserDefinedFunctions, true, false), (DynamicTypeLoadingEnabled, CoreResources.ExperimentalFeatureNames_DynamicTypeLoading, true, false), (ProviderRegistryEnabled, CoreResources.ExperimentalFeatureNames_ProviderRegistry, true, false), (TestFrameworkEnabled, CoreResources.ExperimentalFeatureNames_TestFramework, false, false), diff --git a/src/Bicep.Core/Semantics/DeclarationVisitor.cs b/src/Bicep.Core/Semantics/DeclarationVisitor.cs index a40a72010fd..fb4e0426969 100644 --- a/src/Bicep.Core/Semantics/DeclarationVisitor.cs +++ b/src/Bicep.Core/Semantics/DeclarationVisitor.cs @@ -326,12 +326,7 @@ public override void VisitCompileTimeImportDeclarationSyntax(CompileTimeImportDe { ExportedTypeMetadata exportedType => new ImportedTypeSymbol(context, item, syntax, model, exportedType), ExportedVariableMetadata exportedVariable => new ImportedVariableSymbol(context, item, syntax, model, exportedVariable), - ExportedFunctionMetadata exportedFunction when features.UserDefinedFunctionsEnabled => new ImportedFunctionSymbol(context, item, syntax, model, exportedFunction), - ExportedFunctionMetadata => new ErroredImportSymbol(context, - importedOriginalName, - item, - item.Name, - ImmutableArray.Create(DiagnosticBuilder.ForPosition(item.OriginalSymbolName).FuncDeclarationStatementsUnsupported())), + ExportedFunctionMetadata exportedFunction => new ImportedFunctionSymbol(context, item, syntax, model, exportedFunction), _ when exportMetadata.Kind == ExportMetadataKind.Error => new ErroredImportSymbol(context, importedOriginalName, item, diff --git a/src/Bicep.Core/TypeSystem/TypeAssignmentVisitor.cs b/src/Bicep.Core/TypeSystem/TypeAssignmentVisitor.cs index 4eb691771ee..c8429c88625 100644 --- a/src/Bicep.Core/TypeSystem/TypeAssignmentVisitor.cs +++ b/src/Bicep.Core/TypeSystem/TypeAssignmentVisitor.cs @@ -1831,11 +1831,6 @@ public override void VisitInstanceFunctionCallSyntax(InstanceFunctionCallSyntax return ErrorType.Create(DiagnosticBuilder.ForPosition(syntax.Name).ObjectRequiredForMethodAccess(baseType)); } - if (binder.GetSymbolInfo(syntax.BaseExpression) is WildcardImportSymbol && !features.UserDefinedFunctionsEnabled) - { - errors.Add(DiagnosticBuilder.ForPosition(syntax).FuncDeclarationStatementsUnsupported()); - } - foreach (TypeSymbol argumentType in this.GetArgumentTypes(syntax.Arguments).ToArray()) { CollectErrors(errors, argumentType); diff --git a/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs b/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs index feec1f1f1e7..4dd0d812e61 100644 --- a/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/CompletionTests.cs @@ -56,8 +56,6 @@ public class CompletionTests private static readonly SharedLanguageHelperManager ServerWithBuiltInTypes = new(); - private static readonly SharedLanguageHelperManager ServerWithUDFsEnabled = new(); - private static readonly SharedLanguageHelperManager ServerWithResourceTypedParamsEnabled = new(); [NotNull] @@ -91,11 +89,6 @@ public static void ClassInitialize(TestContext testContext) testContext, services => services.WithFeatureOverrides(new(testContext, ExtensibilityEnabled: true)))); - ServerWithUDFsEnabled.Initialize( - async () => await MultiFileLanguageServerHelper.StartLanguageServer( - testContext, - services => services.WithFeatureOverrides(new(testContext, UserDefinedFunctionsEnabled: true)))); - ServerWithBuiltInTypes.Initialize( async () => await MultiFileLanguageServerHelper.StartLanguageServer( testContext, @@ -2538,7 +2531,7 @@ public async Task Func_definition_lambda_completions_do_not_suggest_outer_variab func foo(innerVar string) string => '${|}' """); - var file = await new ServerRequestHelper(TestContext, ServerWithUDFsEnabled).OpenFile(text); + var file = await new ServerRequestHelper(TestContext, DefaultServer).OpenFile(text); var completions = await file.RequestCompletion(cursor); completions.Should().NotContain(x => x.Label == "outerVar"); @@ -2560,7 +2553,7 @@ func bar() string = 'asdf' func foo(innerVar string) string => '${|}' """); - var file = await new ServerRequestHelper(TestContext, ServerWithUDFsEnabled).OpenFile(text); + var file = await new ServerRequestHelper(TestContext, DefaultServer).OpenFile(text); var completions = await file.RequestCompletion(cursor); completions.Should().Contain(x => x.Label == "bar"); @@ -2573,19 +2566,6 @@ func foo(innerVar string) string => '${bar()|}' """); } - [TestMethod] - public async Task Func_keyword_completion_is_not_offered_if_experimental_feature_not_enabeld() - { - var (text, cursor) = ParserHelper.GetFileWithSingleCursor(@" -f| -"); - - var file = await new ServerRequestHelper(TestContext, DefaultServer).OpenFile(text); - - var completions = await file.RequestCompletion(cursor); - completions.Should().NotContain(x => x.Label == "func"); - } - [TestMethod] public async Task Func_keyword_completion_provides_snippet() { @@ -2593,7 +2573,7 @@ public async Task Func_keyword_completion_provides_snippet() f| "); - var file = await new ServerRequestHelper(TestContext, ServerWithUDFsEnabled).OpenFile(text); + var file = await new ServerRequestHelper(TestContext, DefaultServer).OpenFile(text); var completions = await file.RequestCompletion(cursor); var updatedFile = file.ApplyCompletion(completions, "func", "foo", "string"); @@ -2615,7 +2595,7 @@ public async Task Func_lambda_output_type_completions_only_suggest_types(string {before} """); - var file = await new ServerRequestHelper(TestContext, ServerWithUDFsEnabled).OpenFile(text); + var file = await new ServerRequestHelper(TestContext, DefaultServer).OpenFile(text); var completions = await file.RequestCompletion(cursor); var updatedFile = file.ApplyCompletion(completions, "string"); @@ -2634,7 +2614,7 @@ public async Task Func_lambda_argument_type_completions_only_suggest_types(strin {before} """); - var file = await new ServerRequestHelper(TestContext, ServerWithUDFsEnabled).OpenFile(text); + var file = await new ServerRequestHelper(TestContext, DefaultServer).OpenFile(text); var completions = await file.RequestCompletion(cursor); var updatedFile = file.ApplyCompletion(completions, "string"); @@ -2654,7 +2634,7 @@ public async Task Func_lambda_argument_name_offers_no_completions(string before) {before} """); - var file = await new ServerRequestHelper(TestContext, ServerWithUDFsEnabled).OpenFile(text); + var file = await new ServerRequestHelper(TestContext, DefaultServer).OpenFile(text); var completions = await file.RequestCompletion(cursor); completions.Should().BeEmpty(); @@ -2670,7 +2650,7 @@ func isTrue(input bool) bool => !(input == false) var test = is| """); - var file = await new ServerRequestHelper(TestContext, ServerWithUDFsEnabled).OpenFile(text); + var file = await new ServerRequestHelper(TestContext, DefaultServer).OpenFile(text); var completions = await file.RequestCompletion(cursor); diff --git a/src/Bicep.LangServer.IntegrationTests/DefinitionTests.cs b/src/Bicep.LangServer.IntegrationTests/DefinitionTests.cs index f0259819ee3..32a7ae8c0f8 100644 --- a/src/Bicep.LangServer.IntegrationTests/DefinitionTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/DefinitionTests.cs @@ -705,7 +705,6 @@ public async Task Goto_definition_works_with_cherrypick_arm_function_import_stat """); using var server = await MultiFileLanguageServerHelper.StartLanguageServer(TestContext, services => services - .WithFeatureOverrides(new(TestContext, UserDefinedFunctionsEnabled: true)) .WithFileResolver(new InMemoryFileResolver(new Dictionary { {new("file:///mod.json"), moduleContents}, @@ -758,7 +757,6 @@ public async Task Goto_definition_works_with_arm_wildcard_instance_function_invo """); using var server = await MultiFileLanguageServerHelper.StartLanguageServer(TestContext, services => services - .WithFeatureOverrides(new(TestContext, UserDefinedFunctionsEnabled: true)) .WithFileResolver(new InMemoryFileResolver(new Dictionary { {new("file:///mod.json"), moduleContents}, diff --git a/src/Bicep.LangServer.IntegrationTests/SignatureHelpTests.cs b/src/Bicep.LangServer.IntegrationTests/SignatureHelpTests.cs index 9be87f40620..4aa64e8d14a 100644 --- a/src/Bicep.LangServer.IntegrationTests/SignatureHelpTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/SignatureHelpTests.cs @@ -150,8 +150,8 @@ func isTrue(input bool) bool => !(input == false) var test = isTrue(|) "); - using var server = await MultiFileLanguageServerHelper.StartLanguageServer(TestContext, services => services.WithFeatureOverrides(new(UserDefinedFunctionsEnabled: true))); - var file = await new ServerRequestHelper(TestContext, server).OpenFile(text); + var helper = await DefaultServer.GetAsync(); + var file = await new ServerRequestHelper(TestContext, helper).OpenFile(text); var signatureHelp = await file.RequestSignatureHelp(cursor); var signature = signatureHelp!.Signatures.Single(); diff --git a/src/Bicep.LangServer/Completions/BicepCompletionProvider.cs b/src/Bicep.LangServer/Completions/BicepCompletionProvider.cs index df36a0c3d5c..6241730dc83 100644 --- a/src/Bicep.LangServer/Completions/BicepCompletionProvider.cs +++ b/src/Bicep.LangServer/Completions/BicepCompletionProvider.cs @@ -156,14 +156,11 @@ private IEnumerable GetDeclarationCompletions(SemanticModel mode yield return CreateKeywordCompletion(LanguageConstants.TestKeyword, "Test keyword", context.ReplacementRange); } - if (model.Features.UserDefinedFunctionsEnabled) - { - yield return CreateContextualSnippetCompletion( - LanguageConstants.FunctionKeyword, - "Function declaration", - "func ${1:name}() ${2:outputType} => $0", - context.ReplacementRange); - } + yield return CreateContextualSnippetCompletion( + LanguageConstants.FunctionKeyword, + "Function declaration", + "func ${1:name}() ${2:outputType} => $0", + context.ReplacementRange); if (model.Features.AssertsEnabled) { diff --git a/src/highlightjs/test/baselines/bicepconfig.json b/src/highlightjs/test/baselines/bicepconfig.json deleted file mode 100644 index e9860dc4b44..00000000000 --- a/src/highlightjs/test/baselines/bicepconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "experimentalFeaturesEnabled": { - "userDefinedFunctions": true - } -} diff --git a/src/monarch/test/baselines/bicepconfig.json b/src/monarch/test/baselines/bicepconfig.json deleted file mode 100644 index e9860dc4b44..00000000000 --- a/src/monarch/test/baselines/bicepconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "experimentalFeaturesEnabled": { - "userDefinedFunctions": true - } -} diff --git a/src/textmate/test/baselines/bicepconfig.json b/src/textmate/test/baselines/bicepconfig.json deleted file mode 100644 index e9860dc4b44..00000000000 --- a/src/textmate/test/baselines/bicepconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "experimentalFeaturesEnabled": { - "userDefinedFunctions": true - } -} diff --git a/src/vscode-bicep/schemas/bicepconfig.schema.json b/src/vscode-bicep/schemas/bicepconfig.schema.json index a89f81a43e4..9a3c950e022 100644 --- a/src/vscode-bicep/schemas/bicepconfig.schema.json +++ b/src/vscode-bicep/schemas/bicepconfig.schema.json @@ -719,10 +719,6 @@ "type": "boolean", "description": "Enables basic source mapping to map an error location returned in the ARM template layer back to the relevant location in the Bicep file. See https://aka.ms/bicep/experimental-features#sourcemapping" }, - "userDefinedFunctions": { - "type": "boolean", - "description": "Allows you to define your own custom functions. See https://aka.ms/bicep/experimental-features#userdefinedfunctions" - }, "legacyFormatter": { "type": "boolean", "description": "Enables code formatting using the legacy formatter. See https://aka.ms/bicep/experimental-features#legacyformatter" From 6b33760e6fccd53213e3a56e236a1ea910c172f6 Mon Sep 17 00:00:00 2001 From: Anthony Martin <38542602+anthony-c-martin@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:57:14 -0500 Subject: [PATCH 2/2] Enable symbolic name codegen if UDFs are used --- src/Bicep.Core/Emit/EmitterSettings.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Bicep.Core/Emit/EmitterSettings.cs b/src/Bicep.Core/Emit/EmitterSettings.cs index 87fd8c42f84..cb5319f9bf2 100644 --- a/src/Bicep.Core/Emit/EmitterSettings.cs +++ b/src/Bicep.Core/Emit/EmitterSettings.cs @@ -22,6 +22,8 @@ public EmitterSettings(SemanticModel model) model.Features.SymbolicNameCodegenEnabled || // there are any user-defined type declarations model.Root.TypeDeclarations.Any() || + // there are any user-defined function declarations + model.Root.FunctionDeclarations.Any() || // there are any compile-time imports (imported functions or variables may enclose user-defined types, and determining definitively requires calculating the full import closure) model.Root.ImportedSymbols.Any() || // there are any wildcard compile-time imports