Skip to content
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

Merged
merged 30 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c3cabe1
Rename Import* syntax kinds to Provider*
jeskew Jun 14, 2023
cb03a8d
Add support for compile-time imports to parser
jeskew Jun 27, 2023
594547f
Add feature flag for compile-time imports
jeskew Jun 27, 2023
1ef9d68
Add @export() decorator for types
jeskew Jun 29, 2023
e4e489e
Integrate imports into type system and module dispatcher
jeskew Jul 5, 2023
df81fb6
Tweak merge
jeskew Jul 17, 2023
232a832
Add support for LS completions
jeskew Jul 19, 2023
41fe9dd
Emit imported type symbols in compiled template
jeskew Jul 24, 2023
de138d7
Try to break import closure info calculation into separate steps
jeskew Jul 25, 2023
25e4f49
Move inner classes into separate files
jeskew Jul 25, 2023
0318593
Ensure @export() is targeting top-level type statement
jeskew Jul 25, 2023
4d0a2e2
Merge branch 'main' into jeskew/imports
jeskew Jul 25, 2023
2308e26
Improve compile-time import diagnostic messaging
jeskew Jul 26, 2023
d4bdc01
Implement go to definition for import symbols
jeskew Jul 26, 2023
928ccba
Regenerate baselines and fix failing tests
jeskew Jul 26, 2023
ecbb177
Augment compile time import completions
jeskew Jul 26, 2023
7206eb4
Fixup message formatting
jeskew Jul 27, 2023
b6eabe8
Fix failing tests
jeskew Jul 27, 2023
aa0f8f5
Use an incrementing counter rather than hashes to create unique names…
jeskew Jul 27, 2023
2a691da
Augment hover support on imported symbols and properties thereof
jeskew Jul 27, 2023
9a6329d
Ensure registry module restoration works as expected for `import` and…
jeskew Jul 27, 2023
700884d
Add ARM source template support for go-to-definition on imported symbols
jeskew Jul 27, 2023
69d84ac
Merge branch 'main' into jeskew/imports
jeskew Jul 30, 2023
e6cfd34
Inject import origin info into type definition metadata for imported …
jeskew Jul 30, 2023
c4b435f
Merge branch 'main' into jeskew/imports
jeskew Aug 1, 2023
9224888
Merge branch 'main' into jeskew/imports
jeskew Aug 2, 2023
6bf9e25
Merge branch 'main' into jeskew/imports
jeskew Aug 2, 2023
838d75c
Merge branch 'main' into jeskew/imports
jeskew Aug 3, 2023
0b292b2
Use ToImmutableDictionary instead of CreateRange
jeskew Aug 4, 2023
41e11e0
Merge branch 'main' into jeskew/imports
jeskew Aug 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge branch 'main' into jeskew/imports
  • Loading branch information
jeskew committed Jul 30, 2023
commit 69d84acff6f7b3b7509ff3f737ae3736105db1b8
16 changes: 8 additions & 8 deletions src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void Compile_time_imports_are_disabled_unless_feature_is_enabled()

result.Should().HaveDiagnostics(new[]
{
("BCP354", DiagnosticLevel.Error, "Using compile-time import statements requires enabling EXPERIMENTAL feature \"CompileTimeImports\"."),
("BCP355", DiagnosticLevel.Error, "Using compile-time import statements requires enabling EXPERIMENTAL feature \"CompileTimeImports\"."),
});
}

Expand All @@ -46,7 +46,7 @@ public void Importing_unexported_symbol_should_raise_diagnostic()

result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]
{
("BCP357", DiagnosticLevel.Error, "The 'foo' symbol was not found in (or was not exported by) the imported template."),
("BCP358", DiagnosticLevel.Error, "The 'foo' symbol was not found in (or was not exported by) the imported template."),
});
}

Expand Down Expand Up @@ -80,7 +80,7 @@ public void Exporting_type_property_should_raise_diagnostic()

result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]
{
("BCP358", DiagnosticLevel.Error, "The \"@export()\" decorator must target a top-level statement.")
("BCP359", DiagnosticLevel.Error, "The \"@export()\" decorator must target a top-level statement.")
});
}

Expand All @@ -102,7 +102,7 @@ param bar string

result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]
{
("BCP356", DiagnosticLevel.Error, "A compile-time import can only reference a Bicep file, an ARM template, a registry artifact, or a template spec.")
("BCP357", DiagnosticLevel.Error, "A compile-time import can only reference a Bicep file, an ARM template, a registry artifact, or a template spec.")
});
}

Expand Down Expand Up @@ -403,8 +403,8 @@ public void Importing_the_same_symbol_under_two_separate_names_should_raise_diag

result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]
{
("BCP359", DiagnosticLevel.Error, "This symbol is imported multiple times under the names 'foo', 'fizz'."),
("BCP359", DiagnosticLevel.Error, "This symbol is imported multiple times under the names 'foo', 'fizz'."), // The same diagnostic should be raised on each import
("BCP360", DiagnosticLevel.Error, "This symbol is imported multiple times under the names 'foo', 'fizz'."),
("BCP360", DiagnosticLevel.Error, "This symbol is imported multiple times under the names 'foo', 'fizz'."), // The same diagnostic should be raised on each import
});
}

Expand Down Expand Up @@ -435,8 +435,8 @@ public void Importing_the_same_symbol_from_json_template_under_two_separate_name

result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]
{
("BCP359", DiagnosticLevel.Error, "This symbol is imported multiple times under the names 'foo', 'fizz'."),
("BCP359", DiagnosticLevel.Error, "This symbol is imported multiple times under the names 'foo', 'fizz'."), // The same diagnostic should be raised on each import
("BCP360", DiagnosticLevel.Error, "This symbol is imported multiple times under the names 'foo', 'fizz'."),
("BCP360", DiagnosticLevel.Error, "This symbol is imported multiple times under the names 'foo', 'fizz'."), // The same diagnostic should be raised on each import
});
}
}
23 changes: 14 additions & 9 deletions src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1971,49 +1971,54 @@ public ErrorDiagnostic RuntimeValueNotAllowedInFunctionDeclaration(string? acces
"BCP350",
$"Value of type \"{valueType}\" cannot be assigned to an assert. Asserts can take values of type 'bool' only.");

public ErrorDiagnostic ExpectedSymbolListOrWildcard() => new(
public ErrorDiagnostic FunctionOnlyValidWithDirectAssignment(string functionName) => new(
TextSpan,
"BCP351",
$"Function \"{functionName}\" is not valid at this location. It can only be used when directly assigning to a parameter.");

public ErrorDiagnostic ExpectedSymbolListOrWildcard() => new(
TextSpan,
"BCP352",
"Expected left brace ('{') or asterisk ('*') character at this location.");

public ErrorDiagnostic ExpectedExportedSymbolName() => new(
TextSpan,
"BCP352",
"BCP353",
"Expected the name of an exported symbol at this location.");

public ErrorDiagnostic ExpectedNamespaceIdentifier() => new(
TextSpan,
"BCP353",
"BCP354",
"Expected a valid namespace identifier at this location.");

public ErrorDiagnostic CompileTimeImportsNotSupported() => new(
TextSpan,
"BCP354",
"BCP355",
$@"Using compile-time import statements requires enabling EXPERIMENTAL feature ""{nameof(ExperimentalFeaturesEnabled.CompileTimeImports)}"".");

public ErrorDiagnostic PathHasNotBeenSpecified() => new(
TextSpan,
"BCP355",
"BCP356",
"This declaration is missing a template file path reference.");

public ErrorDiagnostic CompileTimeImportDeclarationMustReferenceTemplate() => new(
TextSpan,
"BCP356",
"BCP357",
"A compile-time import can only reference a Bicep file, an ARM template, a registry artifact, or a template spec.");

public ErrorDiagnostic ImportedSymbolNotFound(string symbolName) => new(
TextSpan,
"BCP357",
"BCP358",
$"The '{symbolName}' symbol was not found in (or was not exported by) the imported template.");

public ErrorDiagnostic ExportDecoratorMustTargetStatement() => new(
TextSpan,
"BCP358",
"BCP359",
@"The ""@export()"" decorator must target a top-level statement.");

public ErrorDiagnostic SymbolImportedMultipleTimes(params string[] importedAs) => new(
TextSpan,
"BCP359",
"BCP360",
$"This symbol is imported multiple times under the names {string.Join(", ", importedAs.Select(identifier => $"'{identifier}'"))}.");
}

Expand Down
32 changes: 10 additions & 22 deletions src/Bicep.Core/Emit/TemplateWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ private static ObjectExpression ApplyTypeModifiers(TypeDeclaringExpression expre
result = result.MergeProperty("additionalProperties", ExpressionFactory.CreateBooleanLiteral(false, @sealed.SourceSyntax));
}

if (expression is DeclaredTypeExpression declaredTypeExpression && declaredTypeExpression.Exported is {} exported)
{
result = ApplyMetadataProperty(result, LanguageConstants.MetadataExportedPropertyName, ExpressionFactory.CreateBooleanLiteral(true, exported.SourceSyntax));
}

foreach (var (modifier, propertyName) in new[]
{
(expression.Metadata, LanguageConstants.ParameterMetadataPropertyName),
Expand All @@ -215,24 +220,7 @@ private static ObjectExpression ApplyTypeModifiers(TypeDeclaringExpression expre
(expression.MinValue, LanguageConstants.ParameterMinValuePropertyName),
(expression.MaxValue, LanguageConstants.ParameterMaxValuePropertyName),
}) {
modifications.Add(new(modifier, (result, nonNullModifier) => result.MergeProperty(propertyName, nonNullModifier)));
}

modifications.Add(new(expression.Description, (result, _) => ApplyDescription(expression, result)));

if (expression is DeclaredTypeExpression declaredTypeExpression)
{
modifications.Add(new(declaredTypeExpression.Exported, (result, exported) => ApplyMetadataProperty(result,
LanguageConstants.MetadataExportedPropertyName,
ExpressionFactory.CreateBooleanLiteral(true, exported.SourceSyntax))));
}

// Whether one decorator overrides another is determined by their order in the syntax tree
// TODO should we change this?
if (expression.SourceSyntax is DecorableSyntax decorable)
{
ConcurrentDictionary<TypeModification, int> modificationIndices = new();
int GetIndex(TypeModification modification)
if (modifier is not null)
{
result = result.MergeProperty(propertyName, modifier);
}
Expand Down Expand Up @@ -321,7 +309,7 @@ private void EmitTypeDeclaration(ExpressionEmitter emitter, DeclaredTypeExpressi
declaredType.SourceSyntax);
}

private static ObjectExpression TypePropertiesForTypeExpression(TypeExpression typeExpression) => typeExpression switch
private ObjectExpression TypePropertiesForTypeExpression(TypeExpression typeExpression) => typeExpression switch
{
// references
AmbientTypeReferenceExpression ambientTypeReference
Expand Down Expand Up @@ -419,7 +407,7 @@ private static ObjectExpression GetTypePropertiesForResourceType(ResourceTypeExp
});
}

private static ObjectExpression GetTypePropertiesForArrayType(ArrayTypeExpression expression)
private ObjectExpression GetTypePropertiesForArrayType(ArrayTypeExpression expression)
{
var properties = new List<ObjectPropertyExpression> { TypeProperty(LanguageConstants.ArrayType, expression.SourceSyntax) };

Expand Down Expand Up @@ -452,7 +440,7 @@ TupleTypeExpression tuple when TypeHelper.IsLiteralType(tuple.ExpressedType) =>
private static ArrayExpression GetAllowedValuesForUnionType(UnionType unionType, SyntaxBase? sourceSyntax)
=> ExpressionFactory.CreateArray(unionType.Members.Select(ToLiteralValue), sourceSyntax);

private static ObjectExpression GetTypePropertiesForObjectType(ObjectTypeExpression expression)
private ObjectExpression GetTypePropertiesForObjectType(ObjectTypeExpression expression)
{
var properties = new List<ObjectPropertyExpression> { TypeProperty(LanguageConstants.ObjectType, expression.SourceSyntax) };
List<ObjectPropertyExpression> propertySchemata = new();
Expand All @@ -479,7 +467,7 @@ private static ObjectExpression GetTypePropertiesForObjectType(ObjectTypeExpress
return ExpressionFactory.CreateObject(properties, expression.SourceSyntax);
}

private static ObjectExpression GetTypePropertiesForTupleType(TupleTypeExpression expression) => ExpressionFactory.CreateObject(new[]
private ObjectExpression GetTypePropertiesForTupleType(TupleTypeExpression expression) => ExpressionFactory.CreateObject(new[]
{
TypeProperty(LanguageConstants.ArrayType, expression.SourceSyntax),
ExpressionFactory.CreateObjectProperty("prefixItems",
Expand Down
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.