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

Conversation

jeskew
Copy link
Contributor

@jeskew jeskew commented Oct 16, 2022

This PR adds a type keyword that can be used to declare user-defined type symbols, as well as a parser and grammar for describing custom structure, typed array, and union types. The types that can be declared in a type statement (or as the type clause of a param statement) include:

  • literal types and literal type unions (e.g., true, 'fizz'|'buzz', 1|2|3, {foo: 'bar'}|{ping: 'pong'})
    type booleanLiteral = true
    type integerLiteral = -100
    type unionOfStringLiterals = 'fizz'|'buzz'|'pop'
  • typed arrays (including arrays of a mixed type but with strictly defined allowed values)
    type arrayOfInts = int[]
    type intsBuriedUnderAnAvalancheOfArrays = int[][][][][][][][][][]
    type mixedTypeArray = (1|false|null|{ping: 'pong'}|'It was the best of times'|'It was the worst of times')[]
  • objects with known properties and individual property schemata
    type myObject = {
        requiredProp: string
        optionalProp?: string[]
        recursiveProp?: myObject
        inlineObjectProperty: {
            nested: 'fizz'|'buzz'
        }
    }
    
    param inlineObjectParam {
        property: string
    }

Types are included in the compiled ARM JSON template and will be enforced by the ARM runtime. Everything is disabled by default and requires an explicit feature flag to opt in. Also, map types and tuple types are not included in this PR. Given those caveats, this PR works towards #4158 but does not resolve it.

Microsoft Reviewers: Open in CodeFlow

@jeskew jeskew marked this pull request as ready for review October 18, 2022 21:42
@@ -89,7 +89,8 @@ public void Map_function_preserves_types_accurately_integers()
var (file, cursors) = ParserHelper.GetFileWithCursors(@"
Copy link
Member

Choose a reason for hiding this comment

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

Rather than have it be customizable per-test, could we just come up with a different character or sequence of characters? ~ feels open, for example, or we could do something like |>. Could always make the char param optional to provide an escape hatch if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Making this configurable per test was a request that came up during the discussions meeting, as you can't currently use logical or tokens in cursor tests. The idea was that not including a default forces the test writer to choose a character that does not appear in the test; this would also help by making cursor ambiguity a caller error rather than incorrect test behavior.

There were specific objections to every single character token on the US qwerty layout, which is why I ended up using ǂ in hover and completion tests with type unions (though any single UCS-2 character that doesn't appear on the keyboard would be fine).

@shenglol
Copy link
Contributor

Found an edge case that makes me think maybe we should block using keywords as symbolic names:
image

@jeskew
Copy link
Contributor Author

jeskew commented Oct 28, 2022

Found an edge case that makes me think maybe we should block using keywords as symbolic names: image

I can add an error for type resource = (similar to the error that is currently raised for type string = or type int =), but I'm not sure if I can get rid of the parser error. param myParam resource 'RP/resourceType@apiVersion' will parse just fine on the main branch, as the feature flag for resource-typed params and outputs isn't checked at the parser level but only in the type manager. The parser is hard coded to look for a resource type immediately following the resource keyword in a param statement's type clause, and the right hand side of the equals sign in a type declaration follows the same rules.

@shenglol
Copy link
Contributor

I can add an error for type resource = (similar to the error that is currently raised for type string = or type int =), but I'm not sure if I can get rid of the parser error. param myParam resource 'RP/resourceType@apiVersion' will parse just fine on the main branch, as the feature flag for resource-typed params and outputs isn't checked at the parser level but only in the type manager. The parser is hard coded to look for a resource type immediately following the resource keyword in a param statement's type clause, and the right hand side of the equals sign in a type declaration follows the same rules.

I think as long as type resource = is blocked, the parser error will be legit since there is no ambiguity.

_ => valueIfFalse,
};

private bool HasSecureDecorator(DecorableSyntax syntax)
Copy link
Member

Choose a reason for hiding this comment

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

Would be nice to have a common place to put these - extension method on IBinder or DecorableSyntax?

public static DecoratorSyntax? TryGetSecureDecorator(this IBinder binder, DecorableSyntax syntax)
public static DecoratorSyntax? TryGetSecureDecorator(this DecorableSyntax syntax, IBinder binder)

@jeskew jeskew force-pushed the jeskew/type-declarations branch 2 times, most recently from 24b4037 to d764457 Compare October 28, 2022 20:10
Copy link
Member

@anthony-c-martin anthony-c-martin left a comment

Choose a reason for hiding this comment

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

Looks good! I think there are still a few comments, but nothing blocking from my perspective.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants