@@ -1095,6 +1095,12 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
1095
1095
}
1096
1096
1097
1097
case tok::identifier: // foo
1098
+ // If starts with 'type(', parse the 'type(of: ...)' metatype expression
1099
+ if (Tok.getText () == " type" && peekToken ().is (tok::l_paren)) {
1100
+ Result = parseExprTypeOf ();
1101
+ break ;
1102
+ }
1103
+
1098
1104
// If we are parsing a refutable pattern and are inside a let/var pattern,
1099
1105
// the identifiers change to be value bindings instead of decl references.
1100
1106
// Parse and return this as an UnresolvedPatternExpr around a binding. This
@@ -1413,12 +1419,22 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
1413
1419
}
1414
1420
1415
1421
// Handle "x.dynamicType" - A metatype expr.
1422
+ // Deprecated in SE-0096: `x.dynamicType` becomes `type(of: x)`
1416
1423
if (Tok.is (tok::kw_dynamicType)) {
1424
+ // Fix-it
1425
+ auto range = Result.get ()->getSourceRange ();
1426
+ auto dynamicTypeExprRange = SourceRange (TokLoc, consumeToken ());
1427
+ diagnose (TokLoc, diag::expr_dynamictype_deprecated)
1428
+ .highlight (dynamicTypeExprRange)
1429
+ .fixItReplace (dynamicTypeExprRange, " )" )
1430
+ .fixItInsert (range.Start , " type(of: " );
1431
+
1417
1432
Result = makeParserResult (
1418
- new (Context) DynamicTypeExpr (Result.get (), consumeToken () , Type ()));
1433
+ new (Context) DynamicTypeExpr (Result.get (), dynamicTypeExprRange. End , Type ()));
1419
1434
continue ;
1420
1435
}
1421
1436
1437
+
1422
1438
// Handle "x.self" expr.
1423
1439
if (Tok.is (tok::kw_self)) {
1424
1440
Result = makeParserResult (
@@ -2995,3 +3011,63 @@ Parser::parseVersionConstraintSpec() {
2995
3011
return makeParserResult (new (Context) VersionConstraintAvailabilitySpec (
2996
3012
Platform.getValue (), PlatformLoc, Version, VersionRange));
2997
3013
}
3014
+
3015
+ // / parseExprTypeOf
3016
+ // /
3017
+ // / expr-dynamictype:
3018
+ // / 'type' '(' 'of:' expr ')'
3019
+ // /
3020
+ ParserResult<Expr> Parser::parseExprTypeOf () {
3021
+
3022
+ assert (Tok.getText () == " type" && " only 'type' should be handled here" );
3023
+
3024
+ // Consume 'type'
3025
+ SourceLoc keywordLoc = consumeToken ();
3026
+ // Consume '('
3027
+ SourceLoc lParenLoc = consumeToken (tok::l_paren);
3028
+
3029
+ // Parse `of` label
3030
+ // If we see a potential argument label followed by a ':', consume
3031
+ // it.
3032
+ if (Tok.canBeArgumentLabel () && Tok.getText () == " of" && peekToken ().is (tok::colon)) {
3033
+ consumeToken ();
3034
+ consumeToken (tok::colon);
3035
+ } else {
3036
+ diagnose (Tok, diag::expr_typeof_expected_label_of);
3037
+ return makeParserError ();
3038
+ }
3039
+
3040
+ // Parse the subexpression.
3041
+ ParserResult<Expr> subExpr = parseExpr (diag::expr_typeof_expected_expr);
3042
+ if (subExpr.hasCodeCompletion ())
3043
+ return makeParserCodeCompletionResult<Expr>();
3044
+
3045
+ // Parse the closing ')'
3046
+ SourceLoc rParenLoc;
3047
+ if (subExpr.isParseError ()) {
3048
+ skipUntilDeclStmtRBrace (tok::r_paren);
3049
+ if (Tok.is (tok::r_paren))
3050
+ rParenLoc = consumeToken ();
3051
+ else
3052
+ rParenLoc = Tok.getLoc ();
3053
+ } else {
3054
+ parseMatchingToken (tok::r_paren, rParenLoc,
3055
+ diag::expr_typeof_expected_rparen, lParenLoc);
3056
+ }
3057
+
3058
+ // If the subexpression was in error, just propagate the error.
3059
+ if (subExpr.isParseError ()) {
3060
+ if (subExpr.hasCodeCompletion ()) {
3061
+ auto res = makeParserResult (
3062
+ new (Context) DynamicTypeExpr (subExpr.get (), consumeToken (), Type ()));
3063
+ res.setHasCodeCompletion ();
3064
+ return res;
3065
+ } else {
3066
+ return makeParserResult<Expr>(
3067
+ new (Context) ErrorExpr (SourceRange (keywordLoc, rParenLoc)));
3068
+ }
3069
+ }
3070
+
3071
+ return makeParserResult (
3072
+ new (Context) DynamicTypeExpr (subExpr.get (), rParenLoc, Type ()));
3073
+ }
0 commit comments