Skip to content

Commit 619fbe1

Browse files
committed
[CodeCompletion] Don't perform completion at declaration name position
If there's expected signature after the code completion. For example: func <HERE>(arg: Int) {} This is clearly modifying the function name. We should not perform any completion including override completion. rdar://problem/58378950
1 parent 8408c33 commit 619fbe1

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

lib/Parse/ParseDecl.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4331,6 +4331,21 @@ parseIdentifierDeclName(Parser &P, Identifier &Result, SourceLoc &Loc,
43314331
return makeParserError();
43324332
}
43334333

4334+
// If there is expected tokens after the code completion token, just eat the
4335+
// code completion token. We don't need code completion here.
4336+
// E.g.:
4337+
// 'func' <completion> ('('|'<')
4338+
// 'typealias' <completion> ('='|'<')
4339+
// If there's no expected token after the completion, override completion may
4340+
// kicks in. So leave the token here.
4341+
// E.g.
4342+
// 'func' <completion>
4343+
// 'init' <completion>
4344+
if (P.Tok.is(tok::code_complete) && canRecover(P.peekToken())) {
4345+
P.consumeToken(tok::code_complete);
4346+
return makeParserCodeCompletionStatus();
4347+
}
4348+
43344349
P.diagnose(P.Tok, diag::expected_identifier_in_decl, DeclKindName);
43354350
return makeParserError();
43364351
}
@@ -4882,7 +4897,7 @@ parseDeclTypeAlias(Parser::ParseDeclOptions Flags, DeclAttributes &Attributes) {
48824897
[](const Token &next) { return next.isAny(tok::colon, tok::equal); });
48834898
if (Status.isError()) {
48844899
TmpCtxt->setTransparent();
4885-
return nullptr;
4900+
return Status;
48864901
}
48874902

48884903
DebuggerContextChange DCC(*this, Id, DeclKind::TypeAlias);
@@ -4998,8 +5013,8 @@ ParserResult<TypeDecl> Parser::parseDeclAssociatedType(Parser::ParseDeclOptions
49985013
*this, Id, IdLoc, "associatedtype",
49995014
[](const Token &next) { return next.isAny(tok::colon, tok::equal); });
50005015
if (Status.isError())
5001-
return nullptr;
5002-
5016+
return Status;
5017+
50035018
DebuggerContextChange DCC(*this, Id, DeclKind::AssociatedType);
50045019

50055020
// Reject generic parameters with a specific error.
@@ -6237,7 +6252,7 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
62376252
startsWithLess(next);
62386253
});
62396254
if (NameStatus.isError())
6240-
return nullptr;
6255+
return NameStatus;
62416256
}
62426257

62436258
DebuggerContextChange DCC(*this, SimpleName, DeclKind::Func);
@@ -6510,7 +6525,7 @@ ParserResult<EnumDecl> Parser::parseDeclEnum(ParseDeclOptions Flags,
65106525
return next.isAny(tok::colon, tok::l_brace) || startsWithLess(next);
65116526
});
65126527
if (Status.isError())
6513-
return nullptr;
6528+
return Status;
65146529

65156530
DebuggerContextChange DCC(*this, EnumName, DeclKind::Enum);
65166531

@@ -6792,7 +6807,7 @@ ParserResult<StructDecl> Parser::parseDeclStruct(ParseDeclOptions Flags,
67926807
return next.isAny(tok::colon, tok::l_brace) || startsWithLess(next);
67936808
});
67946809
if (Status.isError())
6795-
return nullptr;
6810+
return Status;
67966811

67976812
DebuggerContextChange DCC (*this, StructName, DeclKind::Struct);
67986813

@@ -6885,7 +6900,7 @@ ParserResult<ClassDecl> Parser::parseDeclClass(ParseDeclOptions Flags,
68856900
return next.isAny(tok::colon, tok::l_brace) || startsWithLess(next);
68866901
});
68876902
if (Status.isError())
6888-
return nullptr;
6903+
return Status;
68896904

68906905
DebuggerContextChange DCC (*this, ClassName, DeclKind::Class);
68916906

@@ -7005,7 +7020,7 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) {
70057020
*this, ProtocolName, NameLoc, "protocol",
70067021
[&](const Token &next) { return next.isAny(tok::colon, tok::l_brace); });
70077022
if (Status.isError())
7008-
return nullptr;
7023+
return Status;
70097024

70107025
// Protocols don't support generic parameters, but people often want them and
70117026
// we want to have good error recovery if they try them out. Parse them and

test/IDE/complete_declname.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-keywords=false -code-completion-token=METHODNAME_PROTOCOL | %FileCheck %s --check-prefix=NO_COMPLETIONS
1919
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-keywords=false -code-completion-token=METHODNAME_CONFORMANCE | %FileCheck %s --check-prefix=METHODNAME_CONFORMANCE
2020
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-keywords=false -code-completion-token=TYPEALIASNAME_CONFORMANCE | %FileCheck %s --check-prefix=TYPEALIASNAME_CONFORMANCE
21+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-keywords=false -code-completion-token=METHODNAME_HASSIG | %FileCheck %s --check-prefix=NO_COMPLETIONS
22+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-keywords=false -code-completion-token=TYPEALIASNAME_HASSIG | %FileCheck %s --check-prefix=NO_COMPLETIONS
2123

2224
// NO_COMPLETIONS-NOT: Begin completions
2325

@@ -59,8 +61,15 @@ struct MyStruct : P {
5961
// METHODNAME_CONFORMANCE: Begin completions, 1 items
6062
// METHODNAME_CONFORMANCE-NEXT: Decl[InstanceMethod]/Super: foo() {|}; name=foo()
6163
// METHODNAME_CONFORMANCE-NEXT: End completions
64+
6265
typealias #^TYPEALIASNAME_CONFORMANCE^#
6366
// TYPEALIASNAME_CONFORMANCE: Begin completions, 1 items
6467
// TYPEALIASNAME_CONFORMANCE-NEXT: Decl[AssociatedType]/Super: Assoc = {#(Type)#}; name=Assoc = Type
6568
// TYPEALIASNAME_CONFORMANCE-NEXT: End completions
6669
}
70+
struct MyStruct2: P {
71+
func #^METHODNAME_HASSIG^#() (<#parameters#>} {}
72+
// INVALID
73+
typealias #^TYPEALIASNAME_HASSIG^# = <#type#>
74+
// INVALID
75+
}

0 commit comments

Comments
 (0)