@@ -2819,6 +2819,101 @@ static PatternBindingInitializer *findAttributeInitContent(
2819
2819
return nullptr ;
2820
2820
}
2821
2821
2822
+ bool Parser::isCustomAttributeArgument () {
2823
+ BacktrackingScope backtrack (*this );
2824
+ skipSingle ();
2825
+
2826
+ // If we have any keyword, identifier, or token that follows a function
2827
+ // type's parameter list, this is a parameter list and not an attribute.
2828
+ // Alternatively, we might have a token that illustrates we're not going to
2829
+ // get anything following the attribute, which means the parentheses describe
2830
+ // what follows the attribute.
2831
+ return !Tok.isAny (
2832
+ tok::arrow, tok::kw_throw, tok::kw_throws, tok::kw_rethrows,
2833
+ tok::r_paren, tok::r_brace, tok::r_square, tok::r_angle) &&
2834
+ !Tok.isContextualKeyword (" async" ) && !Tok.isContextualKeyword (" reasync" ) ;
2835
+ }
2836
+
2837
+ bool Parser::canParseCustomAttribute () {
2838
+ if (!canParseType ())
2839
+ return false ;
2840
+
2841
+ if (Tok.isFollowingLParen () && isCustomAttributeArgument ())
2842
+ skipSingle ();
2843
+
2844
+ return true ;
2845
+ }
2846
+
2847
+ ParserResult<CustomAttr> Parser::parseCustomAttribute (
2848
+ SourceLoc atLoc, PatternBindingInitializer *&initContext) {
2849
+ SyntaxContext->setCreateSyntax (SyntaxKind::CustomAttribute);
2850
+
2851
+ // Parse a custom attribute.
2852
+ auto type = parseType (diag::expected_type);
2853
+ if (type.hasCodeCompletion () || type.isNull ()) {
2854
+ if (Tok.is (tok::l_paren) && isCustomAttributeArgument ())
2855
+ skipSingle ();
2856
+
2857
+ return ParserResult<CustomAttr>(ParserStatus (type));
2858
+ }
2859
+
2860
+ // Parse the optional arguments.
2861
+ SourceLoc lParenLoc, rParenLoc;
2862
+ SmallVector<Expr *, 2 > args;
2863
+ SmallVector<Identifier, 2 > argLabels;
2864
+ SmallVector<SourceLoc, 2 > argLabelLocs;
2865
+ SmallVector<TrailingClosure, 2 > trailingClosures;
2866
+ bool hasInitializer = false ;
2867
+
2868
+ // If we're not in a local context, we'll need a context to parse
2869
+ // initializers into (should we have one). This happens for properties
2870
+ // and global variables in libraries.
2871
+ ParserStatus status;
2872
+ if (Tok.isFollowingLParen () && isCustomAttributeArgument ()) {
2873
+ if (peekToken ().is (tok::code_complete)) {
2874
+ consumeToken (tok::l_paren);
2875
+ if (CodeCompletion) {
2876
+ auto typeE = new (Context) TypeExpr (type.get ());
2877
+ auto CCE = new (Context) CodeCompletionExpr (Tok.getLoc ());
2878
+ CodeCompletion->completePostfixExprParen (typeE, CCE);
2879
+ }
2880
+ consumeToken (tok::code_complete);
2881
+ skipUntil (tok::r_paren);
2882
+ consumeIf (tok::r_paren);
2883
+ status.setHasCodeCompletionAndIsError ();
2884
+ } else {
2885
+ // If we have no local context to parse the initial value into, create
2886
+ // one for the PBD we'll eventually create. This allows us to have
2887
+ // reasonable DeclContexts for any closures that may live inside of
2888
+ // initializers.
2889
+ Optional<ParseFunctionBody> initParser;
2890
+ if (!CurDeclContext->isLocalContext ()) {
2891
+ if (!initContext) {
2892
+ initContext =
2893
+ new (Context) PatternBindingInitializer (CurDeclContext);
2894
+ }
2895
+
2896
+ initParser.emplace (*this , initContext);
2897
+ }
2898
+ status |= parseExprList (tok::l_paren, tok::r_paren,
2899
+ /* isPostfix=*/ false , /* isExprBasic=*/ true ,
2900
+ lParenLoc, args, argLabels, argLabelLocs,
2901
+ rParenLoc,
2902
+ trailingClosures,
2903
+ SyntaxKind::TupleExprElementList);
2904
+ assert (trailingClosures.empty () && " Cannot parse a trailing closure here" );
2905
+ hasInitializer = true ;
2906
+ }
2907
+ }
2908
+
2909
+ // Form the attribute.
2910
+ auto *TE = new (Context) TypeExpr (type.get ());
2911
+ auto customAttr = CustomAttr::create (Context, atLoc, TE, hasInitializer,
2912
+ initContext, lParenLoc, args, argLabels,
2913
+ argLabelLocs, rParenLoc);
2914
+ return makeParserResult (status, customAttr);
2915
+ }
2916
+
2822
2917
// / \verbatim
2823
2918
// / attribute:
2824
2919
// / '_silgen_name' '(' identifier ')'
@@ -2843,7 +2938,9 @@ static PatternBindingInitializer *findAttributeInitContent(
2843
2938
// / but rejected since they have context-sensitive keywords.
2844
2939
// /
2845
2940
ParserStatus Parser::parseDeclAttribute (
2846
- DeclAttributes &Attributes, SourceLoc AtLoc, bool isFromClangAttribute) {
2941
+ DeclAttributes &Attributes, SourceLoc AtLoc,
2942
+ PatternBindingInitializer *&initContext,
2943
+ bool isFromClangAttribute) {
2847
2944
// If this not an identifier, the attribute is malformed.
2848
2945
if (Tok.isNot (tok::identifier) &&
2849
2946
Tok.isNot (tok::kw_in) &&
@@ -2963,74 +3060,11 @@ ParserStatus Parser::parseDeclAttribute(
2963
3060
diagnose (Tok, diag::unknown_attribute, " unknown" );
2964
3061
} else {
2965
3062
// Change the context to create a custom attribute syntax.
2966
- SyntaxContext->setCreateSyntax (SyntaxKind::CustomAttribute);
2967
- // Parse a custom attribute.
2968
- auto type = parseType (diag::expected_type);
2969
- if (type.hasCodeCompletion () || type.isNull ()) {
2970
- if (Tok.is (tok::l_paren))
2971
- skipSingle ();
2972
-
2973
- return ParserStatus (type);
2974
- }
2975
-
2976
- // Parse the optional arguments.
2977
- SourceLoc lParenLoc, rParenLoc;
2978
- SmallVector<Expr *, 2 > args;
2979
- SmallVector<Identifier, 2 > argLabels;
2980
- SmallVector<SourceLoc, 2 > argLabelLocs;
2981
- SmallVector<TrailingClosure, 2 > trailingClosures;
2982
- bool hasInitializer = false ;
2983
- ParserStatus status;
2984
-
2985
- // If we're not in a local context, we'll need a context to parse
2986
- // initializers into (should we have one). This happens for properties
2987
- // and global variables in libraries.
2988
- PatternBindingInitializer *initContext = nullptr ;
2989
-
2990
- if (Tok.isFollowingLParen ()) {
2991
- if (peekToken ().is (tok::code_complete)) {
2992
- consumeToken (tok::l_paren);
2993
- if (CodeCompletion) {
2994
- auto typeE = new (Context) TypeExpr (type.get ());
2995
- auto CCE = new (Context) CodeCompletionExpr (Tok.getLoc ());
2996
- CodeCompletion->completePostfixExprParen (typeE, CCE);
2997
- }
2998
- consumeToken (tok::code_complete);
2999
- skipUntil (tok::r_paren);
3000
- consumeIf (tok::r_paren);
3001
- status.setHasCodeCompletionAndIsError ();
3002
- } else {
3003
- // If we have no local context to parse the initial value into, create
3004
- // one for the PBD we'll eventually create. This allows us to have
3005
- // reasonable DeclContexts for any closures that may live inside of
3006
- // initializers.
3007
- Optional<ParseFunctionBody> initParser;
3008
- if (!CurDeclContext->isLocalContext ()) {
3009
- initContext = findAttributeInitContent (Attributes);
3010
- if (!initContext)
3011
- initContext =
3012
- new (Context) PatternBindingInitializer (CurDeclContext);
3013
-
3014
- initParser.emplace (*this , initContext);
3015
- }
3016
- status |= parseExprList (tok::l_paren, tok::r_paren,
3017
- /* isPostfix=*/ false , /* isExprBasic=*/ true ,
3018
- lParenLoc, args, argLabels, argLabelLocs,
3019
- rParenLoc,
3020
- trailingClosures,
3021
- SyntaxKind::TupleExprElementList);
3022
- assert (trailingClosures.empty () && " Cannot parse a trailing closure here" );
3023
- hasInitializer = true ;
3024
- }
3025
- }
3063
+ auto customAttr = parseCustomAttribute (AtLoc, initContext);
3064
+ if (auto attr = customAttr.getPtrOrNull ())
3065
+ Attributes.add (attr);
3026
3066
3027
- // Form the attribute.
3028
- auto *TE = new (Context) TypeExpr (type.get ());
3029
- auto attr = CustomAttr::create (Context, AtLoc, TE, hasInitializer,
3030
- initContext, lParenLoc, args, argLabels,
3031
- argLabelLocs, rParenLoc);
3032
- Attributes.add (attr);
3033
- return status;
3067
+ return ParserStatus (customAttr);
3034
3068
}
3035
3069
3036
3070
// Recover by eating @foo(...) when foo is not known.
@@ -3043,7 +3077,8 @@ ParserStatus Parser::parseDeclAttribute(
3043
3077
3044
3078
bool Parser::canParseTypeAttribute () {
3045
3079
TypeAttributes attrs; // ignored
3046
- return !parseTypeAttribute (attrs, /* atLoc=*/ SourceLoc (),
3080
+ PatternBindingInitializer *initContext = nullptr ;
3081
+ return !parseTypeAttribute (attrs, /* atLoc=*/ SourceLoc (), initContext,
3047
3082
/* justChecking*/ true );
3048
3083
}
3049
3084
@@ -3204,6 +3239,7 @@ bool Parser::parseConventionAttributeInternal(
3204
3239
// / canParseTypeAttribute; don't emit any diagnostics, and there's
3205
3240
// / no need to actually record the attribute
3206
3241
bool Parser::parseTypeAttribute (TypeAttributes &Attributes, SourceLoc AtLoc,
3242
+ PatternBindingInitializer *&initContext,
3207
3243
bool justChecking) {
3208
3244
// If this not an identifier, the attribute is malformed.
3209
3245
if (Tok.isNot (tok::identifier) &&
@@ -3218,15 +3254,11 @@ bool Parser::parseTypeAttribute(TypeAttributes &Attributes, SourceLoc AtLoc,
3218
3254
TypeAttrKind attr = TypeAttributes::getAttrKindFromString (Tok.getText ());
3219
3255
3220
3256
if (attr == TAK_Count) {
3221
- if (justChecking) return true ;
3222
-
3223
3257
auto declAttrID = DeclAttribute::getAttrKindFromString (Tok.getText ());
3224
- if (declAttrID == DAK_Count) {
3225
- // Not a decl or type attribute.
3226
- diagnose (Tok, diag::unknown_attribute, Tok.getText ());
3227
- } else {
3228
- // Otherwise this is a valid decl attribute so they should have put it on
3229
- // the decl instead of the type.
3258
+ if (declAttrID != DAK_Count) {
3259
+ // This is a valid decl attribute so they should have put it on the decl
3260
+ // instead of the type.
3261
+ if (justChecking) return true ;
3230
3262
3231
3263
// If this is the first attribute, and if we are on a simple decl, emit a
3232
3264
// fixit to move the attribute. Otherwise, we don't have the location of
@@ -3246,21 +3278,45 @@ bool Parser::parseTypeAttribute(TypeAttributes &Attributes, SourceLoc AtLoc,
3246
3278
.fixItInsert (StructureMarkers.back ().Loc ,
3247
3279
" @" + Tok.getText ().str ()+" " );
3248
3280
}
3281
+
3282
+ // Recover by eating @foo(...) when foo is not known.
3283
+ consumeToken ();
3284
+ SyntaxParsingContext TokListContext (SyntaxContext, SyntaxKind::TokenList);
3285
+
3286
+ if (Tok.is (tok::l_paren) && getEndOfPreviousLoc () == Tok.getLoc ()) {
3287
+ CancellableBacktrackingScope backtrack (*this );
3288
+ skipSingle ();
3289
+ // If we found '->', or 'throws' after paren, it's likely a parameter
3290
+ // of function type.
3291
+ if (Tok.isNot (tok::arrow, tok::kw_throws, tok::kw_rethrows,
3292
+ tok::kw_throw))
3293
+ backtrack.cancelBacktrack ();
3294
+ }
3295
+
3296
+ return true ;
3249
3297
}
3250
-
3251
- // Recover by eating @foo(...) when foo is not known.
3252
- consumeToken ();
3253
- SyntaxParsingContext TokListContext (SyntaxContext, SyntaxKind::TokenList);
3254
3298
3255
- if (Tok.is (tok::l_paren) && getEndOfPreviousLoc () == Tok.getLoc ()) {
3256
- CancellableBacktrackingScope backtrack (*this );
3257
- skipSingle ();
3258
- // If we found '->', or 'throws' after paren, it's likely a parameter
3259
- // of function type.
3260
- if (Tok.isNot (tok::arrow, tok::kw_throws, tok::kw_rethrows,
3261
- tok::kw_throw))
3262
- backtrack.cancelBacktrack ();
3299
+ // If we're just checking, try to parse now.
3300
+ if (justChecking)
3301
+ return !canParseCustomAttribute ();
3302
+
3303
+ // Parse as a custom attribute.
3304
+ auto customAttrResult = parseCustomAttribute (AtLoc, initContext);
3305
+ if (customAttrResult.isParseErrorOrHasCompletion ())
3306
+ return true ;
3307
+
3308
+ // Diagnose the attribute, because we don't yet handle custom type
3309
+ // attributes.
3310
+ std::string typeName;
3311
+ auto customAttr = customAttrResult.get ();
3312
+ if (auto typeRepr = customAttr->getTypeRepr ()) {
3313
+ llvm::raw_string_ostream out (typeName);
3314
+ typeRepr->print (out);
3315
+ } else {
3316
+ typeName = customAttr->getType ().getString ();
3263
3317
}
3318
+
3319
+ diagnose (customAttr->getLocation (), diag::unknown_attribute, typeName);
3264
3320
return true ;
3265
3321
}
3266
3322
@@ -3447,12 +3503,13 @@ ParserStatus Parser::parseDeclAttributeList(DeclAttributes &Attributes) {
3447
3503
if (Tok.isNot (tok::at_sign))
3448
3504
return makeParserSuccess ();
3449
3505
3506
+ PatternBindingInitializer *initContext = nullptr ;
3450
3507
ParserStatus Status;
3451
3508
SyntaxParsingContext AttrListCtx (SyntaxContext, SyntaxKind::AttributeList);
3452
3509
do {
3453
3510
SyntaxParsingContext AttrCtx (SyntaxContext, SyntaxKind::Attribute);
3454
3511
SourceLoc AtLoc = consumeToken ();
3455
- Status |= parseDeclAttribute (Attributes, AtLoc);
3512
+ Status |= parseDeclAttribute (Attributes, AtLoc, initContext );
3456
3513
} while (Tok.is (tok::at_sign));
3457
3514
return Status;
3458
3515
}
@@ -3669,6 +3726,7 @@ bool Parser::parseDeclModifierList(DeclAttributes &Attributes,
3669
3726
bool Parser::parseTypeAttributeListPresent (ParamDecl::Specifier &Specifier,
3670
3727
SourceLoc &SpecifierLoc,
3671
3728
TypeAttributes &Attributes) {
3729
+ PatternBindingInitializer *initContext = nullptr ;
3672
3730
Specifier = ParamDecl::Specifier::Default;
3673
3731
while (Tok.is (tok::kw_inout) ||
3674
3732
(Tok.is (tok::identifier) &&
@@ -3701,7 +3759,7 @@ bool Parser::parseTypeAttributeListPresent(ParamDecl::Specifier &Specifier,
3701
3759
Attributes.AtLoc = Tok.getLoc ();
3702
3760
SyntaxParsingContext AttrCtx (SyntaxContext, SyntaxKind::Attribute);
3703
3761
SourceLoc AtLoc = consumeToken ();
3704
- if (parseTypeAttribute (Attributes, AtLoc))
3762
+ if (parseTypeAttribute (Attributes, AtLoc, initContext ))
3705
3763
return true ;
3706
3764
}
3707
3765
0 commit comments