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

Add experimental support for aggregate type declarations #8673

Merged
merged 39 commits into from
Oct 30, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
3d075a5
Add feature flag for aggregate types
jeskew Oct 14, 2022
d1d848d
Add new syntax classes for type expressions
jeskew Oct 14, 2022
f7b723c
Add type expression parsing to TypeManager
jeskew Oct 14, 2022
c2e0981
Add aggregate type support to TemplateWriter
jeskew Oct 14, 2022
62f6b7d
Add types samples
jeskew Oct 14, 2022
115cc3e
Improve diagnostic reporting by deferring declared type resolution on…
jeskew Oct 15, 2022
139eaef
Make $ref writing purely syntax driven
jeskew Oct 15, 2022
8963dcd
Fixup integer and boolean type literal support
jeskew Oct 16, 2022
706f926
Make sure decorators used on types are valid type decorators
jeskew Oct 16, 2022
76eea10
Run baselines
jeskew Oct 14, 2022
a83d920
Fixup tests
jeskew Oct 16, 2022
dbc7361
Cleanup parameter type assignment when @allowed decorator used
jeskew Oct 17, 2022
06f5e6e
Require cursor-based tests to specify the character that represents a…
jeskew Oct 18, 2022
d8e56e4
Fixup LangServer tests
jeskew Oct 18, 2022
85a54a5
Add rudimentary completions, hovers, and semantic highlighting
jeskew Oct 18, 2022
ef5f5cc
Improve cycle detection and reporting for objects
jeskew Oct 18, 2022
309d0d5
Disallow newlines between union members for now
jeskew Oct 18, 2022
83391e0
Add hover tests
jeskew Oct 18, 2022
cb69c01
Add type keyword to Textmate grammar
jeskew Oct 19, 2022
0a075f8
Merge branch 'main' into jeskew/type-declarations
jeskew Oct 19, 2022
bc2c140
fixup some todos and typos left in PR
jeskew Oct 19, 2022
c8aac0c
Check properties of param default values
jeskew Oct 20, 2022
cc683fe
Better completions for union types
jeskew Oct 20, 2022
ed9c02a
Show warning when an object with additional properties only accepts t…
jeskew Oct 20, 2022
b401bcc
Raise an error diagnostic on user-defined types whose name masks an a…
jeskew Oct 21, 2022
27aa1bb
Merge branch 'main' into jeskew/type-declarations
jeskew Oct 26, 2022
14da820
Update diagnostic messages for clarity
jeskew Oct 26, 2022
bf35acd
Update Highlight.js and Monarch grammars + baselines
jeskew Oct 26, 2022
5d12aac
Rename types vnext feature to 'UserDefinedTypes'
jeskew Oct 26, 2022
26d7d8f
Update grammar to include user-defined types
jeskew Oct 26, 2022
98c1c45
Add types flag to bicepconfig schema
jeskew Oct 27, 2022
72f24da
Rename DeclaredTypeSymbol to TypeAliasSymbol
jeskew Oct 28, 2022
d3b7c13
Block types named 'resource' and update associated diagnostic message
jeskew Oct 28, 2022
30f4037
Check for nested type errors in TypeAssignmentVisitor, not in Semanti…
jeskew Oct 28, 2022
49ca0b3
Remove recursion guard from SymbolVisitor
jeskew Oct 28, 2022
de9d2ac
Cleanup and consolidate per PR feedback
jeskew Oct 28, 2022
cdf7d25
Fix test
jeskew Oct 29, 2022
6f093f0
Improve union type checking
jeskew Oct 29, 2022
9b18e69
Introduce a TypeType type to disallow assignment of types to location…
jeskew Oct 29, 2022
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
Block types named 'resource' and update associated diagnostic message
  • Loading branch information
jeskew committed Oct 28, 2022
commit d3b7c139a7cb18ce6b16a19bb72cff07f629d967
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ type noAssignment

type incompleteAssignment =

type string = string
type string = int

type resource = bool

@sealed()
type sealedString = string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ type noAssignment
type incompleteAssignment =
//@[27:27) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "array", "bool", "int", "object", "string". (CodeDescription: none) ||

type string = string
//@[05:11) [BCP301 (Error)] A user-defined type may not be named "string" because it would mask the ARM type of the same name. (CodeDescription: none) |string|
type string = int
//@[05:11) [BCP301 (Error)] The type name "string" is reserved and may not be attached to a user-defined type. (CodeDescription: none) |string|

type resource = bool
//@[05:13) [BCP301 (Error)] The type name "resource" is reserved and may not be attached to a user-defined type. (CodeDescription: none) |resource|

@sealed()
//@[00:09) [BCP124 (Error)] The decorator "sealed" can only be attached to targets of type "object", but the target has type "string". (CodeDescription: none) |@sealed()|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ type noAssignment

type incompleteAssignment =

type string = string
type string = int

type resource = bool

@sealed()
type sealedString = string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,71 +1,74 @@
type 44
//@[5:07) Type <error>. Type: any. Declaration start char: 0, length: 7
//@[5:07) TypeAlias <error>. Type: any. Declaration start char: 0, length: 7

type noAssignment
//@[5:17) Type noAssignment. Type: any. Declaration start char: 0, length: 17
//@[5:17) TypeAlias noAssignment. Type: any. Declaration start char: 0, length: 17

type incompleteAssignment =
//@[5:25) Type incompleteAssignment. Type: any. Declaration start char: 0, length: 27
//@[5:25) TypeAlias incompleteAssignment. Type: any. Declaration start char: 0, length: 27

type string = string
//@[5:11) Type string. Type: string. Declaration start char: 0, length: 20
type string = int
//@[5:11) TypeAlias string. Type: int. Declaration start char: 0, length: 17

type resource = bool
//@[5:13) TypeAlias resource. Type: bool. Declaration start char: 0, length: 20

@sealed()
type sealedString = string
//@[5:17) Type sealedString. Type: string. Declaration start char: 0, length: 36
//@[5:17) TypeAlias sealedString. Type: string. Declaration start char: 0, length: 36

type disallowedUnion = 'foo'|21
//@[5:20) Type disallowedUnion. Type: error. Declaration start char: 0, length: 31
//@[5:20) TypeAlias disallowedUnion. Type: error. Declaration start char: 0, length: 31

type validStringLiteralUnion = 'foo'|'bar'|'baz'
//@[5:28) Type validStringLiteralUnion. Type: 'bar' | 'baz' | 'foo'. Declaration start char: 0, length: 48
//@[5:28) TypeAlias validStringLiteralUnion. Type: 'bar' | 'baz' | 'foo'. Declaration start char: 0, length: 48

type validUnionInvalidAddition = validStringLiteralUnion|10
//@[5:30) Type validUnionInvalidAddition. Type: error. Declaration start char: 0, length: 59
//@[5:30) TypeAlias validUnionInvalidAddition. Type: error. Declaration start char: 0, length: 59

type invalidUnionInvalidAddition = disallowedUnion|true
//@[5:32) Type invalidUnionInvalidAddition. Type: error. Declaration start char: 0, length: 55
//@[5:32) TypeAlias invalidUnionInvalidAddition. Type: error. Declaration start char: 0, length: 55

type nullLiteral = null
//@[5:16) Type nullLiteral. Type: error. Declaration start char: 0, length: 23
//@[5:16) TypeAlias nullLiteral. Type: error. Declaration start char: 0, length: 23

type unionOfNulls = null|null
//@[5:17) Type unionOfNulls. Type: error. Declaration start char: 0, length: 29
//@[5:17) TypeAlias unionOfNulls. Type: error. Declaration start char: 0, length: 29

@minLength(3)
type lengthConstrainedInt = int
//@[5:25) Type lengthConstrainedInt. Type: int. Declaration start char: 0, length: 45
//@[5:25) TypeAlias lengthConstrainedInt. Type: int. Declaration start char: 0, length: 45

@minValue(3)
type valueConstrainedString = string
//@[5:27) Type valueConstrainedString. Type: string. Declaration start char: 0, length: 49
//@[5:27) TypeAlias valueConstrainedString. Type: string. Declaration start char: 0, length: 49

type tautology = tautology
//@[5:14) Type tautology. Type: error. Declaration start char: 0, length: 26
//@[5:14) TypeAlias tautology. Type: error. Declaration start char: 0, length: 26

type tautologicalUnion = tautologicalUnion|'foo'
//@[5:22) Type tautologicalUnion. Type: error. Declaration start char: 0, length: 48
//@[5:22) TypeAlias tautologicalUnion. Type: error. Declaration start char: 0, length: 48

type tautologicalArray = tautologicalArray[]
//@[5:22) Type tautologicalArray. Type: error. Declaration start char: 0, length: 44
//@[5:22) TypeAlias tautologicalArray. Type: error. Declaration start char: 0, length: 44

type directCycleStart = directCycleReturn
//@[5:21) Type directCycleStart. Type: error. Declaration start char: 0, length: 41
//@[5:21) TypeAlias directCycleStart. Type: error. Declaration start char: 0, length: 41

type directCycleReturn = directCycleStart
//@[5:22) Type directCycleReturn. Type: error. Declaration start char: 0, length: 41
//@[5:22) TypeAlias directCycleReturn. Type: error. Declaration start char: 0, length: 41

type cycleRoot = connector
//@[5:14) Type cycleRoot. Type: error. Declaration start char: 0, length: 26
//@[5:14) TypeAlias cycleRoot. Type: error. Declaration start char: 0, length: 26

type connector = cycleBack
//@[5:14) Type connector. Type: error. Declaration start char: 0, length: 26
//@[5:14) TypeAlias connector. Type: error. Declaration start char: 0, length: 26

type cycleBack = cycleRoot
//@[5:14) Type cycleBack. Type: error. Declaration start char: 0, length: 26
//@[5:14) TypeAlias cycleBack. Type: error. Declaration start char: 0, length: 26

type objectWithInvalidPropertyDecorators = {
//@[5:40) Type objectWithInvalidPropertyDecorators. Type: { fooProp: string, barProp: string, krispyProp: string }. Declaration start char: 0, length: 168
//@[5:40) TypeAlias objectWithInvalidPropertyDecorators. Type: { fooProp: string, barProp: string, krispyProp: string }. Declaration start char: 0, length: 168
@sealed()
fooProp: string

Expand All @@ -77,10 +80,13 @@ type objectWithInvalidPropertyDecorators = {
}

type objectWithInvalidRecursion = {
//@[5:31) Type objectWithInvalidRecursion. Type: error. Declaration start char: 0, length: 92
//@[5:31) TypeAlias objectWithInvalidRecursion. Type: error. Declaration start char: 0, length: 92
requiredAndRecursiveProp: objectWithInvalidRecursion
}

type arrayWithInvalidMember = objectWithInvalidRecursion[]
//@[5:27) TypeAlias arrayWithInvalidMember. Type: error[]. Declaration start char: 0, length: 58

@sealed()
param sealedStringParam string
//@[6:23) Parameter sealedStringParam. Type: string. Declaration start char: 0, length: 40
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
type 44
//@[00:1109) ProgramSyntax
//@[00:1128) ProgramSyntax
//@[00:0007) ├─TypeDeclarationSyntax
//@[00:0004) | ├─Token(Identifier) |type|
//@[05:0007) | ├─IdentifierSyntax
Expand Down Expand Up @@ -27,14 +27,24 @@ type incompleteAssignment =
//@[27:0027) | └─SkippedTriviaSyntax
//@[27:0029) ├─Token(NewLine) |\n\n|

type string = string
//@[00:0020) ├─TypeDeclarationSyntax
type string = int
//@[00:0017) ├─TypeDeclarationSyntax
//@[00:0004) | ├─Token(Identifier) |type|
//@[05:0011) | ├─IdentifierSyntax
//@[05:0011) | | └─Token(Identifier) |string|
//@[12:0013) | ├─Token(Assignment) |=|
//@[14:0020) | └─SimpleTypeSyntax
//@[14:0020) | └─Token(Identifier) |string|
//@[14:0017) | └─SimpleTypeSyntax
//@[14:0017) | └─Token(Identifier) |int|
//@[17:0019) ├─Token(NewLine) |\n\n|

type resource = bool
//@[00:0020) ├─TypeDeclarationSyntax
//@[00:0004) | ├─Token(Identifier) |type|
//@[05:0013) | ├─IdentifierSyntax
//@[05:0013) | | └─Token(Identifier) |resource|
//@[14:0015) | ├─Token(Assignment) |=|
//@[16:0020) | └─SimpleTypeSyntax
//@[16:0020) | └─Token(Identifier) |bool|
//@[20:0022) ├─Token(NewLine) |\n\n|

@sealed()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@ type incompleteAssignment =
//@[26:27) Assignment |=|
//@[27:29) NewLine |\n\n|

type string = string
type string = int
//@[00:04) Identifier |type|
//@[05:11) Identifier |string|
//@[12:13) Assignment |=|
//@[14:20) Identifier |string|
//@[14:17) Identifier |int|
//@[17:19) NewLine |\n\n|

type resource = bool
//@[00:04) Identifier |type|
//@[05:13) Identifier |resource|
//@[14:15) Assignment |=|
//@[16:20) Identifier |bool|
//@[20:22) NewLine |\n\n|

@sealed()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @description('The foo type')
// @sealed()
type foo = {
//@[5:08) Type foo. Type: { stringProp: string, objectProp: { intProp: int, intArrayArrayProp?: int[][] }, typeRefProp: bar, literalProp: 'literal', recursion?: foo }. Declaration start char: 0, length: 262
//@[5:08) TypeAlias foo. Type: { stringProp: string, objectProp: { intProp: int, intArrayArrayProp?: int[][] }, typeRefProp: bar, literalProp: 'literal', recursion?: foo }. Declaration start char: 0, length: 262
@minLength(3)
@maxLength(10)
// @description('A string property')
Expand Down Expand Up @@ -29,19 +29,19 @@ type foo = {
// ]
// })
type bar = int[][][][]
//@[5:08) Type bar. Type: int[][][][]. Declaration start char: 0, length: 181
//@[5:08) TypeAlias bar. Type: int[][][][]. Declaration start char: 0, length: 181

type aUnion = 'snap'|'crackle'|'pop'
//@[5:11) Type aUnion. Type: 'crackle' | 'pop' | 'snap'. Declaration start char: 0, length: 36
//@[5:11) TypeAlias aUnion. Type: 'crackle' | 'pop' | 'snap'. Declaration start char: 0, length: 36

type expandedUnion = aUnion|'fizz'|'buzz'|'pop'
//@[5:18) Type expandedUnion. Type: 'buzz' | 'crackle' | 'fizz' | 'pop' | 'snap'. Declaration start char: 0, length: 47
//@[5:18) TypeAlias expandedUnion. Type: 'buzz' | 'crackle' | 'fizz' | 'pop' | 'snap'. Declaration start char: 0, length: 47

type mixedArray = ('heffalump'|'woozle'|{ shape: '*', size: '*'}|10|-10|true|!true|null)[]
//@[5:15) Type mixedArray. Type: ('heffalump' | 'woozle' | -10 | 10 | false | null | true | { shape: '*', size: '*' })[]. Declaration start char: 0, length: 90
//@[5:15) TypeAlias mixedArray. Type: ('heffalump' | 'woozle' | -10 | 10 | false | null | true | { shape: '*', size: '*' })[]. Declaration start char: 0, length: 90

type String = string
//@[5:11) Type String. Type: string. Declaration start char: 0, length: 20
//@[5:11) TypeAlias String. Type: string. Declaration start char: 0, length: 20

param inlineObjectParam {
//@[6:23) Parameter inlineObjectParam. Type: { foo: string, bar: 100 | 200 | 300 | 400 | 500, baz: bool }. Declaration start char: 0, length: 123
Expand Down
4 changes: 2 additions & 2 deletions src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1710,10 +1710,10 @@ public ErrorDiagnostic UnknownModuleReferenceScheme(string badScheme, ImmutableA
"BCP300",
$"Expected a type literal at this location. Please specify a concrete value or a reference to a literal type.");

public ErrorDiagnostic TypeNameMasksAmbientType(string conflictingName) => new(
public ErrorDiagnostic ReservedTypeName(string reservedName) => new(
TextSpan,
"BCP301",
$@"A user-defined type may not be named ""{conflictingName}"" because it would mask the ARM type of the same name.");
$@"The type name ""{reservedName}"" is reserved and may not be attached to a user-defined type.");

public ErrorDiagnostic SymbolicNameIsNotAType(string name, IEnumerable<string> validTypes) => new(
TextSpan,
Expand Down
2 changes: 2 additions & 0 deletions src/Bicep.Core/LanguageConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ public static class LanguageConstants
// types allowed to use in output and parameter declarations
public static readonly ImmutableSortedDictionary<string, TypeSymbol> DeclarationTypes = new[] { String, Object, Int, Bool, Array }.ToImmutableSortedDictionary(type => type.Name, type => type, StringComparer.Ordinal);

public static readonly ImmutableHashSet<string> ReservedTypeNames = ImmutableHashSet.CreateRange<string>(IdentifierComparer, DeclarationTypes.Keys.Append(ResourceKeyword));

public static TypeSymbol? TryGetDeclarationType(string? typeName)
{
if (typeName != null && DeclarationTypes.TryGetValue(typeName, out var primitiveType))
Expand Down
4 changes: 2 additions & 2 deletions src/Bicep.Core/TypeSystem/TypeAssignmentVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -433,9 +433,9 @@ public override void VisitTypeDeclarationSyntax(TypeDeclarationSyntax syntax)
{
var declaredType = GetDeclaredTypeAndValidateDecorators(syntax, syntax.Value, diagnostics);

if (LanguageConstants.DeclarationTypes.Keys.Any(s => LanguageConstants.IdentifierComparer.Equals(s, syntax.Name.IdentifierName)))
if (LanguageConstants.ReservedTypeNames.Contains(syntax.Name.IdentifierName))
{
diagnostics.Write(DiagnosticBuilder.ForPosition(syntax.Name).TypeNameMasksAmbientType(syntax.Name.IdentifierName));
diagnostics.Write(DiagnosticBuilder.ForPosition(syntax.Name).ReservedTypeName(syntax.Name.IdentifierName));
}

base.VisitTypeDeclarationSyntax(syntax);
Expand Down