2
2
//
3
3
// This source file is part of the Swift.org open source project
4
4
//
5
- // Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5
+ // Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6
6
// Licensed under Apache License v2.0 with Runtime Library Exception
7
7
//
8
8
// See https://swift.org/LICENSE.txt for license information
@@ -2766,6 +2766,7 @@ void Parser::delayParseFromBeginningToHere(ParserPosition BeginParserPosition,
2766
2766
// / \endverbatim
2767
2767
ParserResult<Decl>
2768
2768
Parser::parseDecl (ParseDeclOptions Flags,
2769
+ bool IsAtStartOfLineOrPreviousHadSemi,
2769
2770
llvm::function_ref<void (Decl*)> Handler) {
2770
2771
ParserPosition BeginParserPosition;
2771
2772
if (isCodeCompletionFirstPass ())
@@ -2854,6 +2855,30 @@ Parser::parseDecl(ParseDeclOptions Flags,
2854
2855
auto OrigTok = Tok;
2855
2856
bool MayNeedOverrideCompletion = false ;
2856
2857
2858
+ auto parseLetOrVar = [&](bool HasLetOrVarKeyword) {
2859
+ // Collect all modifiers into a modifier list.
2860
+ DeclParsingContext.setCreateSyntax (SyntaxKind::VariableDecl);
2861
+ llvm::SmallVector<Decl *, 4 > Entries;
2862
+ DeclResult = parseDeclVar (Flags, Attributes, Entries, StaticLoc,
2863
+ StaticSpelling, tryLoc, HasLetOrVarKeyword);
2864
+ StaticLoc = SourceLoc (); // we handled static if present.
2865
+ MayNeedOverrideCompletion = true ;
2866
+ if (DeclResult.hasCodeCompletion () && isCodeCompletionFirstPass ())
2867
+ return ;
2868
+ std::for_each (Entries.begin (), Entries.end (), Handler);
2869
+ if (auto *D = DeclResult.getPtrOrNull ())
2870
+ markWasHandled (D);
2871
+ };
2872
+
2873
+ auto parseFunc = [&](bool HasFuncKeyword) {
2874
+ // Collect all modifiers into a modifier list.
2875
+ DeclParsingContext.setCreateSyntax (SyntaxKind::FunctionDecl);
2876
+ DeclResult = parseDeclFunc (StaticLoc, StaticSpelling, Flags, Attributes,
2877
+ HasFuncKeyword);
2878
+ StaticLoc = SourceLoc (); // we handled static if present.
2879
+ MayNeedOverrideCompletion = true ;
2880
+ };
2881
+
2857
2882
switch (Tok.getKind ()) {
2858
2883
case tok::kw_import:
2859
2884
DeclParsingContext.setCreateSyntax (SyntaxKind::ImportDecl);
@@ -2865,18 +2890,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
2865
2890
break ;
2866
2891
case tok::kw_let:
2867
2892
case tok::kw_var: {
2868
- // Collect all modifiers into a modifier list.
2869
- DeclParsingContext.setCreateSyntax (SyntaxKind::VariableDecl);
2870
- llvm::SmallVector<Decl *, 4 > Entries;
2871
- DeclResult = parseDeclVar (Flags, Attributes, Entries, StaticLoc,
2872
- StaticSpelling, tryLoc);
2873
- StaticLoc = SourceLoc (); // we handled static if present.
2874
- MayNeedOverrideCompletion = true ;
2875
- if (DeclResult.hasCodeCompletion () && isCodeCompletionFirstPass ())
2876
- break ;
2877
- std::for_each (Entries.begin (), Entries.end (), Handler);
2878
- if (auto *D = DeclResult.getPtrOrNull ())
2879
- markWasHandled (D);
2893
+ parseLetOrVar (/* HasLetOrVarKeyword=*/ true );
2880
2894
break ;
2881
2895
}
2882
2896
case tok::kw_typealias:
@@ -2932,11 +2946,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
2932
2946
DeclResult = parseDeclProtocol (Flags, Attributes);
2933
2947
break ;
2934
2948
case tok::kw_func:
2935
- // Collect all modifiers into a modifier list.
2936
- DeclParsingContext.setCreateSyntax (SyntaxKind::FunctionDecl);
2937
- DeclResult = parseDeclFunc (StaticLoc, StaticSpelling, Flags, Attributes);
2938
- StaticLoc = SourceLoc (); // we handled static if present.
2939
- MayNeedOverrideCompletion = true ;
2949
+ parseFunc (/* HasFuncKeyword=*/ true );
2940
2950
break ;
2941
2951
case tok::kw_subscript: {
2942
2952
DeclParsingContext.setCreateSyntax (SyntaxKind::SubscriptDecl);
@@ -2982,6 +2992,33 @@ Parser::parseDecl(ParseDeclOptions Flags,
2982
2992
2983
2993
// Obvious nonsense.
2984
2994
default :
2995
+
2996
+ if (Flags.contains (PD_HasContainerType) &&
2997
+ IsAtStartOfLineOrPreviousHadSemi) {
2998
+
2999
+ // Emit diagnostics if we meet an identifier/operator where a declaration
3000
+ // is expected, perhaps the user forgot the 'func' or 'var' keyword.
3001
+ //
3002
+ // Must not confuse it with trailing closure syntax, so we only
3003
+ // recover in contexts where there can be no statements.
3004
+
3005
+ if ((Tok.isIdentifierOrUnderscore () &&
3006
+ peekToken ().isAny (tok::colon, tok::equal, tok::comma)) ||
3007
+ Tok.is (tok::l_paren)) {
3008
+ diagnose (Tok.getLoc (), diag::expected_keyword_in_decl, " var" ,
3009
+ " property" )
3010
+ .fixItInsert (Tok.getLoc (), " var " );
3011
+ parseLetOrVar (/* HasLetOrVarKeyword=*/ false );
3012
+ break ;
3013
+ } else if (Tok.isIdentifierOrUnderscore () || Tok.isAnyOperator ()) {
3014
+ diagnose (Tok.getLoc (), diag::expected_keyword_in_decl, " func" ,
3015
+ " function" )
3016
+ .fixItInsert (Tok.getLoc (), " func " );
3017
+ parseFunc (/* HasFuncKeyword=*/ false );
3018
+ break ;
3019
+ }
3020
+ }
3021
+
2985
3022
diagnose (Tok, diag::expected_decl);
2986
3023
2987
3024
if (CurDeclContext) {
@@ -3166,7 +3203,9 @@ void Parser::parseDeclDelayed() {
3166
3203
Scope S (this , DelayedState->takeScope ());
3167
3204
ContextChange CC (*this , DelayedState->ParentContext );
3168
3205
3169
- parseDecl (ParseDeclOptions (DelayedState->Flags ), [&](Decl *D) {
3206
+ parseDecl (ParseDeclOptions (DelayedState->Flags ),
3207
+ /* IsAtStartOfLineOrPreviousHadSemi=*/ true ,
3208
+ [&](Decl *D) {
3170
3209
if (auto *parent = DelayedState->ParentContext ) {
3171
3210
if (auto *NTD = dyn_cast<NominalTypeDecl>(parent)) {
3172
3211
NTD->addMember (D);
@@ -3517,7 +3556,9 @@ ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi,
3517
3556
3518
3557
// If the previous declaration didn't have a semicolon and this new
3519
3558
// declaration doesn't start a line, complain.
3520
- if (!PreviousHadSemi && !Tok.isAtStartOfLine () && !Tok.is (tok::unknown)) {
3559
+ const bool IsAtStartOfLineOrPreviousHadSemi =
3560
+ PreviousHadSemi || Tok.isAtStartOfLine () || Tok.is (tok::unknown);
3561
+ if (!IsAtStartOfLineOrPreviousHadSemi) {
3521
3562
auto endOfPrevious = getEndOfPreviousLoc ();
3522
3563
diagnose (endOfPrevious, diag::declaration_same_line_without_semi)
3523
3564
.fixItInsert (endOfPrevious, " ;" );
@@ -3536,7 +3577,7 @@ ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi,
3536
3577
if (loadCurrentSyntaxNodeFromCache ()) {
3537
3578
return ParserStatus ();
3538
3579
}
3539
- Result = parseDecl (Options, handler);
3580
+ Result = parseDecl (Options, IsAtStartOfLineOrPreviousHadSemi, handler);
3540
3581
if (Result.isParseError ())
3541
3582
skipUntilDeclRBrace (tok::semi, tok::pound_endif);
3542
3583
SourceLoc SemiLoc;
@@ -5134,7 +5175,8 @@ Parser::parseDeclVar(ParseDeclOptions Flags,
5134
5175
SmallVectorImpl<Decl *> &Decls,
5135
5176
SourceLoc StaticLoc,
5136
5177
StaticSpellingKind StaticSpelling,
5137
- SourceLoc TryLoc) {
5178
+ SourceLoc TryLoc,
5179
+ bool HasLetOrVarKeyword) {
5138
5180
assert (StaticLoc.isInvalid () || StaticSpelling != StaticSpellingKind::None);
5139
5181
5140
5182
if (StaticLoc.isValid ()) {
@@ -5152,9 +5194,11 @@ Parser::parseDeclVar(ParseDeclOptions Flags,
5152
5194
}
5153
5195
}
5154
5196
5155
- bool isLet = Tok.is (tok::kw_let);
5156
- assert (Tok.getKind () == tok::kw_let || Tok.getKind () == tok::kw_var);
5157
- SourceLoc VarLoc = consumeToken ();
5197
+ bool isLet = HasLetOrVarKeyword && Tok.is (tok::kw_let);
5198
+ assert (!HasLetOrVarKeyword || Tok.getKind () == tok::kw_let ||
5199
+ Tok.getKind () == tok::kw_var);
5200
+
5201
+ SourceLoc VarLoc = HasLetOrVarKeyword ? consumeToken () : Tok.getLoc ();
5158
5202
5159
5203
// If this is a var in the top-level of script/repl source file, wrap the
5160
5204
// PatternBindingDecl in a TopLevelCodeDecl, since it represents executable
@@ -5464,9 +5508,11 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,
5464
5508
// / \endverbatim
5465
5509
// /
5466
5510
// / \note The caller of this method must ensure that the next token is 'func'.
5467
- ParserResult<FuncDecl>
5468
- Parser::parseDeclFunc (SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
5469
- ParseDeclOptions Flags, DeclAttributes &Attributes) {
5511
+ ParserResult<FuncDecl> Parser::parseDeclFunc (SourceLoc StaticLoc,
5512
+ StaticSpellingKind StaticSpelling,
5513
+ ParseDeclOptions Flags,
5514
+ DeclAttributes &Attributes,
5515
+ bool HasFuncKeyword) {
5470
5516
assert (StaticLoc.isInvalid () || StaticSpelling != StaticSpellingKind::None);
5471
5517
5472
5518
if (StaticLoc.isValid ()) {
@@ -5488,7 +5534,8 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
5488
5534
}
5489
5535
}
5490
5536
5491
- SourceLoc FuncLoc = consumeToken (tok::kw_func);
5537
+ SourceLoc FuncLoc =
5538
+ HasFuncKeyword ? consumeToken (tok::kw_func) : Tok.getLoc ();
5492
5539
5493
5540
// Parse function name.
5494
5541
Identifier SimpleName;
0 commit comments