Skip to content

Conversation

@levimatheri
Copy link
Contributor

@levimatheri levimatheri commented Jan 26, 2026

Description

  • Added support for extension namespace functions
    • Enabled extension keyword in bicepparam files
    • Updated external input function emit to work with LanguageExpression. This is because the extension namespace function may define the expression that it should be reduced to which may not necessarily be the same as the function syntax.
    • Updated external input baselines to fix duplicate external input definitions generated by the same syntax.

Example Usage

Namespace function definition:

{
  "$type": "NamespaceFunctionType",
  "name": "config",
  "description": "Reads configuration from external tooling",
  "evaluatedLanguageExpression": "[externalInput('ext.expression', concat('$config(', parameters('configKey'), ')'))]",
  "parameters": [
    {
      "name": "configKey",
      "type": {
        "$ref": "#/0" // StringType
      },
      "description": "The configuration key parameter",
      "flags": 3 // Required | CompileTimeConstant
    }
  ],
  "outputType": {
    "$ref": "#/3" // AnyType
  },
  "visibleInFileKind": 2 // bicepparam
}

Bicepparam:

using none
extension ext
param redisConfig = json(ext.config('redis'))

Compiled json:

{
  "parameters": {
    "redisConfig": {
      "expression": "[json(externalInputs('ext_expression_0'))]"
    }
  },
  "externalInputDefinitions": {
    "ext_expression_0": {
      "kind": "ext.expression",
      "config": "$config(redis)"
    }
  }
}

Checklist

Microsoft Reviewers: Open in CodeFlow

@github-actions
Copy link
Contributor

github-actions bot commented Jan 26, 2026

Test this change out locally with the following install scripts (Action run 21645183295)

VSCode
  • Mac/Linux
    bash <(curl -Ls https://aka.ms/bicep/nightly-vsix.sh) --run-id 21645183295
  • Windows
    iex "& { $(irm https://aka.ms/bicep/nightly-vsix.ps1) } -RunId 21645183295"
Azure CLI
  • Mac/Linux
    bash <(curl -Ls https://aka.ms/bicep/nightly-cli.sh) --run-id 21645183295
  • Windows
    iex "& { $(irm https://aka.ms/bicep/nightly-cli.ps1) } -RunId 21645183295"

@levimatheri levimatheri marked this pull request as ready for review January 26, 2026 19:55
Comment on lines 27 to 30
("main.bicep", new("""
extension '../extension.tgz' as ext
var foo = ext.config('redis')
""")),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Nit]: With """ blocks, multiline snippets don't have to be flush with the left margin. I try to keep them bounded by one indentation level past the line they appear in, but opinions on what's most readable vary.

// Ideally extension namespace function authors shouldn't need to set this flag in the types.json at all if they have externalInputs in the "evaluatesTo" property
// Consider using visitor pattern to determine this automatically
if (!functionSymbol.FunctionFlags.HasFlag(FunctionFlags.RequiresExternalInput))
catch (Exception)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to make this more specific? What exceptions are expected here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added handling and unit test for ExpressionException if there is a failure running the arm expression evaluator.

if (intermediate is not FunctionCallExpression functionExpression || functionExpression.Parameters.Length < 1)
private void CollectExternalInputs(FunctionCallSyntaxBase sourceSyntax, FunctionExpression functionExpression)
{
if (!functionExpression.NameEquals(LanguageConstants.ExternalInputBicepFunctionName))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is NameEquals case insensitive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's case-insensitive.

public static bool NameEquals(this FunctionExpression expression, string name)
=> StringComparer.OrdinalIgnoreCase.Equals(expression.Function, name);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a couple of tests here? I think there should be tests covering:

  1. The result of one namespace function being passed as an argument to another.
  2. A namespace function where externalInput is part of a function property

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

@levimatheri levimatheri force-pushed the levi/extension-namespace-functions branch from c378ace to 4f6e5df Compare February 3, 2026 19:47
@levimatheri levimatheri requested a review from jeskew February 3, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants