@@ -2705,6 +2705,22 @@ parseIdentifierDeclName(Parser &P, Identifier &Result, SourceLoc &L,
2705
2705
ResyncP1, Diagnostic (ID, Args...));
2706
2706
}
2707
2707
2708
+ // / Add a fix-it to remove the space in consecutive identifiers.
2709
+ // / Add a camel-cased option if it is different than the first option.
2710
+ void Parser::diagnoseConsecutiveIDs (Token First, Token Second) {
2711
+ auto Joined = (First.getText () + Second.getText ()).str ();
2712
+ SourceRange Range (First.getLoc (), Second.getLoc ());
2713
+ diagnose (Second.getLoc (), diag::join_identifiers).fixItReplace (Range, Joined);
2714
+
2715
+ SmallString<8 > Scratch;
2716
+ auto SentenceCased = camel_case::toSentencecase (Tok.getText (), Scratch);
2717
+ auto CamelCased = (First.getText () + SentenceCased).str ();
2718
+ if (Joined != CamelCased) {
2719
+ diagnose (Second.getLoc (), diag::join_identifiers_camel_case)
2720
+ .fixItReplace (Range, CamelCased);
2721
+ }
2722
+ }
2723
+
2708
2724
// / Parse a Decl item in decl list.
2709
2725
static ParserStatus parseDeclItem (Parser &P,
2710
2726
bool &PreviousHadSemi,
@@ -2722,9 +2738,20 @@ static ParserStatus parseDeclItem(Parser &P,
2722
2738
// If the previous declaration didn't have a semicolon and this new
2723
2739
// declaration doesn't start a line, complain.
2724
2740
if (!PreviousHadSemi && !P.Tok .isAtStartOfLine () && !P.Tok .is (tok::unknown)) {
2725
- auto endOfPrevious = P.getEndOfPreviousLoc ();
2726
- P.diagnose (endOfPrevious, diag::declaration_same_line_without_semi)
2727
- .fixItInsert (endOfPrevious, " ;" );
2741
+ // Add a fix-it to remove the space in consecutive identifiers
2742
+ // in a property or enum case decl.
2743
+ auto PreviousTok = P.L ->getTokenAt (P.PreviousLoc );
2744
+ if (P.Tok .is (tok::identifier) && PreviousTok.is (tok::identifier)) {
2745
+ auto enumContext = P.CurDeclContext ->getAsEnumOrEnumExtensionContext ();
2746
+ auto TypeName = enumContext ? " enum case" : " property" ;
2747
+ P.diagnose (P.Tok .getLoc (), diag::repeated_identifier, TypeName);
2748
+ P.diagnoseConsecutiveIDs (PreviousTok, P.Tok );
2749
+ P.skipUntilDeclRBrace (tok::semi, tok::pound_endif);
2750
+ } else {
2751
+ auto endOfPrevious = P.getEndOfPreviousLoc ();
2752
+ P.diagnose (endOfPrevious, diag::declaration_same_line_without_semi)
2753
+ .fixItInsert (endOfPrevious, " ;" );
2754
+ }
2728
2755
}
2729
2756
2730
2757
auto Result = P.parseDecl (Options, handler);
@@ -4661,26 +4688,7 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
4661
4688
// space or newline accidentally.
4662
4689
if (Tok.isIdentifierOrUnderscore () && SimpleName.str ().back () != ' <' ) {
4663
4690
diagnose (Tok.getLoc (), diag::repeated_identifier, " function" );
4664
-
4665
- SourceRange DoubleIdentifierRange (NameLoc, Tok.getLoc ());
4666
-
4667
- // Provide two fix-its: a direct concatenation of the two identifiers
4668
- // and a camel-cased version.
4669
-
4670
- auto DirectConcatenation = NameTok.getText ().str () + Tok.getText ().str ();
4671
-
4672
- diagnose (Tok.getLoc (), diag::join_identifiers)
4673
- .fixItReplace (DoubleIdentifierRange, DirectConcatenation);
4674
-
4675
- SmallString<8 > CapitalizedScratch;
4676
- auto Capitalized = camel_case::toSentencecase (Tok.getText (),
4677
- CapitalizedScratch);
4678
- auto CamelCaseConcatenation = NameTok.getText ().str () + Capitalized.str ();
4679
-
4680
- if (DirectConcatenation != CamelCaseConcatenation)
4681
- diagnose (Tok.getLoc (), diag::join_identifiers_camel_case)
4682
- .fixItReplace (DoubleIdentifierRange, CamelCaseConcatenation);
4683
-
4691
+ diagnoseConsecutiveIDs (NameTok, Tok);
4684
4692
consumeToken ();
4685
4693
}
4686
4694
}
@@ -4941,6 +4949,14 @@ ParserResult<EnumDecl> Parser::parseDeclEnum(ParseDeclOptions Flags,
4941
4949
ED->setGenericParams (GenericParams);
4942
4950
}
4943
4951
4952
+ // Add a fix-it to remove the space in consecutive identifiers
4953
+ // in an enum decl.
4954
+ if (Tok.is (tok::identifier)) {
4955
+ diagnose (Tok.getLoc (), diag::repeated_identifier, " enum" );
4956
+ diagnoseConsecutiveIDs (L->getTokenAt (EnumNameLoc), Tok);
4957
+ consumeToken ();
4958
+ }
4959
+
4944
4960
SourceLoc LBLoc, RBLoc;
4945
4961
if (parseToken (tok::l_brace, LBLoc, diag::expected_lbrace_enum)) {
4946
4962
LBLoc = PreviousLoc;
@@ -5196,6 +5212,14 @@ ParserResult<StructDecl> Parser::parseDeclStruct(ParseDeclOptions Flags,
5196
5212
SD->setGenericParams (GenericParams);
5197
5213
}
5198
5214
5215
+ // Add a fix-it to remove the space in consecutive identifiers
5216
+ // in a struct decl.
5217
+ if (Tok.is (tok::identifier)) {
5218
+ diagnose (Tok.getLoc (), diag::repeated_identifier, " struct" );
5219
+ diagnoseConsecutiveIDs (L->getTokenAt (StructNameLoc), Tok);
5220
+ consumeToken ();
5221
+ }
5222
+
5199
5223
SourceLoc LBLoc, RBLoc;
5200
5224
if (parseToken (tok::l_brace, LBLoc, diag::expected_lbrace_struct)) {
5201
5225
LBLoc = PreviousLoc;
@@ -5279,6 +5303,14 @@ ParserResult<ClassDecl> Parser::parseDeclClass(SourceLoc ClassLoc,
5279
5303
CD->setGenericParams (GenericParams);
5280
5304
}
5281
5305
5306
+ // Add a fix-it to remove the space in consecutive identifiers
5307
+ // in a class decl.
5308
+ if (Tok.is (tok::identifier)) {
5309
+ diagnose (Tok.getLoc (), diag::repeated_identifier, " class" );
5310
+ diagnoseConsecutiveIDs (L->getTokenAt (ClassNameLoc), Tok);
5311
+ consumeToken ();
5312
+ }
5313
+
5282
5314
SourceLoc LBLoc, RBLoc;
5283
5315
if (parseToken (tok::l_brace, LBLoc, diag::expected_lbrace_class)) {
5284
5316
LBLoc = PreviousLoc;
0 commit comments