-
Notifications
You must be signed in to change notification settings - Fork 815
Description
Bicep version
0.39.26
Describe the bug
When using extendable parameters feature and referencing the externalInput() function nested inside another function e.g. bool(externalInput()), the child bicepparam file fails to compile with the following diagnostic error:
BCP(338) Failed to evaluate parameter "": The template function 'externalInput' is not valid. Please see https://aka.ms/arm-functions for usage details.
To Reproduce
- Create a bicep file (main.bicep):
param trafficManagerEnabled bool
param endpointWeight int- Create a parent bicepparam file (main.bicepparam):
using none
param trafficManagerEnabled = bool(externalInput('scopeBinding', '__TRAFFICMANAGER_ENABLED__'))- Create a child bicepparam file (parameters.bicepparam) that extends the main.bicepparam file:
using 'main.bicep'
extends 'main.bicepparam'
param endpointWeight = 50- Enable the
extendableParamFilesexperimental feature flag in the bicepconfig.json file:
{
"experimentalFeaturesEnabled": {
"extendableParamFiles": true
}
}- Observe the error in VSCode or by running
bicep build-params parameters.bicepparam:
Error BCP338: Failed to evaluate parameter "trafficManagerEnabled": The template function 'externalInput' is not valid. Please see https://aka.ms/arm-functions for usage details. [https://aka.ms/bicep/core-diagnostics#BCP338]
Additional context
After some debugging, I narrowed down the offending code to the following method:
If a function's argument is itself a function (like in bool(externalInput(...))), line 180 if-condition is skipped after evaluating line 195.
I think we should include FunctionCallSyntax in the if-check.
bicep/src/Bicep.Core/Semantics/Binder.cs
Lines 168 to 208 in 5acc9f0
| private void ProcessSyntaxForBinding( | |
| SyntaxBase rootSyntax, | |
| IBinder parentBinder, | |
| IDictionary<SyntaxBase, Symbol> baseBindings) | |
| { | |
| var stack = new Stack<SyntaxBase>(); | |
| stack.Push(rootSyntax); | |
| while (stack.Count > 0) | |
| { | |
| var current = stack.Pop(); | |
| if (current is VariableAccessSyntax || current == rootSyntax || current is PropertyAccessSyntax || current is ArrayAccessSyntax) | |
| { | |
| var parentSymbol = parentBinder.GetSymbolInfo(current); | |
| if (parentSymbol is not null && !baseBindings.ContainsKey(current)) | |
| { | |
| baseBindings[current] = parentSymbol; | |
| } | |
| } | |
| var childNodes = current switch | |
| { | |
| ObjectSyntax obj => obj.Properties.Select(p => p.Value), | |
| ArraySyntax arr => arr.Items.Select(i => i.Value), | |
| PropertyAccessSyntax propAccess => [propAccess.BaseExpression], | |
| ArrayAccessSyntax arrayAccess => [arrayAccess.BaseExpression, arrayAccess.IndexExpression], | |
| FunctionCallSyntaxBase funcCall => funcCall.Arguments.Select(a => a.Expression), | |
| ParenthesizedExpressionSyntax paren => [paren.Expression], | |
| TernaryOperationSyntax ternary => [ternary.ConditionExpression, ternary.TrueExpression, ternary.FalseExpression], | |
| BinaryOperationSyntax binary => [binary.LeftExpression, binary.RightExpression], | |
| UnaryOperationSyntax unary => [unary.Expression], | |
| NonNullAssertionSyntax nonNull => [nonNull.BaseExpression], | |
| _ => [] | |
| }; | |
| foreach (var child in childNodes) | |
| { | |
| stack.Push(child); | |
| } | |
| } |
cc @polatengin
Metadata
Metadata
Assignees
Labels
Type
Projects
Status