-
Notifications
You must be signed in to change notification settings - Fork 759
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compile-time type imports #11298
Compile-time type imports #11298
Conversation
37a3d8c
to
6012104
Compare
cc2c513
to
384d8ce
Compare
I remember in the proposal |
It occurred to me while working on the parser that since Bicep already has one means of modifying a statement (decorators), we might not want to introduce a secondary mechanism (auxiliary keywords). Another worry is that a prefix keyword that can be applied to multiple kinds of statements will make dissimilar statements look too much alike, e.g.: // It's easy to scan the left margin and tell what a statement will do.
// Even with decorators and some separating spaces, syntax highlighting makes the first keyword pop
@description('The foo param')
param foo = string
@description('The bar output')
output bar = foo
@description('The baz variable')
@export()
var baz = 'baz'
@description('The quux type')
@export()
type quux = int
// My worry is that once `export` is highlighted as a keyword, `export var` will look more like `export type` than like `var`
export var fizz = 'fizz'
export type buzz = 'buzz' The flip side of this is that an @description('The combination for a four digit lock. Pad from the left with zeroes to four digits if less than 1000')
@metadata({
examples: [
0 // 0000
10 // 0010
100 // 0100
1000 // 1000
]
})
@export()
@minValue(0)
@maxValue(9999)
type lockCombination = int I'll bring this up at a team discussion -- neither approach is problematic to implement, and I'm curious to see what everyone finds easier to read. |
|
||
namespace Bicep.Core.Syntax; | ||
|
||
public class WildcardImportSyntax : SyntaxBase, INamedDeclarationSyntax |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With import * as foo from 'foo.bicep
, will all the members in foo.bicep
be put under a namespace foo
and can only be accessed via the namespace? If so, do we have plans to add support for wildcard imports without alias (import * from 'foo.bicep'
) and default imports (import 'foo.bicep'
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default imports is currently being blocked by provider imports, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to hold off on both default imports and unaliased wildcards. Unaliased wildcards create a situation where your template can start failing to compile because something you're importing added a new symbol whose name clashes with something else defined in your template. Any case where a template starts breaking without changes to the source should be viewed with suspicion IMHO.
For default imports, I'm just not sure if there would be demand. It seems like something we can add later if users ask for it.
This produced no diagnostics ("hi.bicep" is empty): import * as t from 'hi.bicep'
output foo t.fake = '' Is that expected? |
It would be nice if we could make go to definition work on import * as t from 'hi.bicep'
output foo t.fortyTwo = 3 |
… `test` statements
# Conflicts: # src/Bicep.Core/Intermediate/ExpressionBuilder.cs
var importedFromProperties = ExpressionFactory.CreateObjectProperty(LanguageConstants.ImportMetadataSourceTemplatePropertyName, | ||
ExpressionFactory.CreateStringLiteral(originMetadata.SourceTemplateIdentifier)).AsEnumerable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit concerned that we might be exposing too much information here if the symbol comes from a local file, a template spec, or a private module registry.
The format used will either be a path relative to the entrypoint model or a fully qualified ts:
or br:
URI, and the intention is to help with debugging (so that a user can see that a type named 1.foo
in their compiled template came from mod.bicep
or br:mcr.microsoft.com:network/virtual-network:1.0.1
).
This data is also useful for decompilation when the source template is in br/public
, but there's always a chance a local file or private registry module could have an embarrassing or too-revealing name, like templates_from_people_I_am_about_to_fire/mod.bicep
or br:acr.microsoft.com:companyName/templates_we_stole_from_rival_x/storage:1.0.1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I think it would fine to emit the source template information. The the same information already exists in the Bicep file, and the generated template might already contain other confidential data, so emitting the source template information does not inherently introduce new risks. We just need to make sure not to accidentally log the property in the backend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚢
Partially addresses #10121
This PR adds compile-time imports for user-defined types. This feature is only available under a flag and must be enabled with a bicepconfig.json file that looks like this:
With the feature enabled, the
import
keyword can be used to move user-defined types across templates. For example, given the following template saved asmod.bicep
:The
foo
andbar
type symbols can be imported into another template either individually by name using "symbols list" syntax:or with "wildcard" syntax (which is less efficient but more fun to say):
With the "symbols" list syntax, you can import a subset of the target template's exported symbols and rename/alias them at will:
You can also mix and match syntaxes. Symbols will be imported at most once:
Imported types can be used anywhere a user-defined type might be (i.e., within the type clauses of
type
,param
, andoutput
statements).Only types that bear the
@export()
decorator can be imported. As of this PR, this decorator can only be used ontype
statements.Microsoft Reviewers: codeflow:open?pullrequest=#11298