diff --git a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs index 1d0f02440b1..fb792e71262 100644 --- a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs +++ b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs @@ -7537,4 +7537,25 @@ param bar true result.Should().NotHaveAnyDiagnostics(); } + + [TestMethod] + public void Test_Issue17555() + { + var result = CompilationHelper.Compile(""" + metadata name = 'ts-devopspool' + metadata description = 'Creates a managed devops pool' + metadata version = '1.0.0' + + @description('Optional, default value is empty. Resource tags. Dictionary of tag names and values. See Tags in templates') + param parTags object = {} + + #disable-next-line no-unused-vars + var varTags = union(parTags, { + 'ts-name': deployment().properties.template.metadata.name + 'ts-version': deployment().properties.template.metadata.version + }) + """); + + result.Should().NotHaveAnyDiagnostics(); + } } diff --git a/src/Bicep.Core/Semantics/Namespaces/AzNamespaceType.cs b/src/Bicep.Core/Semantics/Namespaces/AzNamespaceType.cs index d3544d932a1..648d7dc3dc0 100644 --- a/src/Bicep.Core/Semantics/Namespaces/AzNamespaceType.cs +++ b/src/Bicep.Core/Semantics/Namespaces/AzNamespaceType.cs @@ -193,8 +193,20 @@ private static ObjectType GetEnvironmentReturnType() }, null); } - private static ObjectType GetDeploymentReturnType(bool resourceGroupScope) + private static FunctionResult GetDeploymentReturnResult(SemanticModel model, IDiagnosticWriter diagnostics, FunctionCallSyntaxBase functionCall, ImmutableArray argumentTypes) { + List templateProperties = [new("contentVersion", LanguageConstants.String)]; + if (model.Root.MetadataDeclarations.Length > 0) + { + templateProperties.Add(new("metadata", new ObjectType( + "metadataProperties", + TypeSymbolValidationFlags.Default, + model.Root.MetadataDeclarations.Select(md => new NamedTypeProperty( + md.Name, + md.Type, + Description: md.TryGetDescriptionFromDecorator(model)))))); + } + // Note: there are other properties which could be included here, but they allow you to break out of the bicep world. // We're going to omit them and only include what is truly necessary. If we get feature requests to expose more properties, we should discuss this further. // Properties such as 'template', 'templateHash', 'parameters' depend on the codegen, and feel like they could be fragile. @@ -204,10 +216,7 @@ private static ObjectType GetDeploymentReturnType(bool resourceGroupScope) new NamedTypeProperty("name", LanguageConstants.String), new NamedTypeProperty("properties", new ObjectType("properties", TypeSymbolValidationFlags.Default, new [] { - new NamedTypeProperty("template", new ObjectType("templateProperties", TypeSymbolValidationFlags.Default, new [] - { - new NamedTypeProperty("contentVersion", LanguageConstants.String) - }, null)), + new NamedTypeProperty("template", new ObjectType("templateProperties", TypeSymbolValidationFlags.Default, templateProperties, null)), new NamedTypeProperty("templateLink", new ObjectType("templateLinkProperties", TypeSymbolValidationFlags.Default, new [] { new NamedTypeProperty("id", LanguageConstants.String), @@ -216,14 +225,14 @@ private static ObjectType GetDeploymentReturnType(bool resourceGroupScope) }, null)), }; - if (!resourceGroupScope) + if (model.TargetScope != ResourceScope.ResourceGroup) { // deployments in the 'resourcegroup' scope do not have the 'location' property. All other scopes do. var locationProperty = new NamedTypeProperty("location", LanguageConstants.String); properties = properties.Concat(locationProperty.AsEnumerable()); } - return new ObjectType("deployment", TypeSymbolValidationFlags.Default, properties, null); + return new(new ObjectType("deployment", TypeSymbolValidationFlags.Default, properties, null)); } private static ObjectType GetDeployerReturnType() @@ -315,17 +324,12 @@ private static ObjectType GetDeployerReturnType() yield return ( new FunctionOverloadBuilder("deployment") - .WithReturnType(GetDeploymentReturnType(resourceGroupScope: true)) + .WithReturnResultBuilder( + GetDeploymentReturnResult, + new ObjectType("deployment", TypeSymbolValidationFlags.Default, [], new TypeProperty(LanguageConstants.Any))) .WithGenericDescription("Returns information about the current deployment operation.") .Build(), - ResourceScope.ResourceGroup); - - yield return ( - new FunctionOverloadBuilder("deployment") - .WithReturnType(GetDeploymentReturnType(resourceGroupScope: false)) - .WithGenericDescription("Returns information about the current deployment operation.") - .Build(), - ResourceScope.Tenant | ResourceScope.ManagementGroup | ResourceScope.Subscription); + ResourceScope.Tenant | ResourceScope.ManagementGroup | ResourceScope.Subscription | ResourceScope.ResourceGroup); yield return ( new FunctionOverloadBuilder("deployer")