Skip to content

Commit 569ea52

Browse files
committed
[Completion] Support multiple parameter specifiers
Allow consuming any parameter specifiers ahead of the completion token when completion for the start of a function parameter type.
1 parent a672af4 commit 569ea52

File tree

4 files changed

+42
-19
lines changed

4 files changed

+42
-19
lines changed

include/swift/Parse/Parser.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,7 @@ class Parser {
12421242
if (next.isAny(tok::at_sign, tok::kw_inout, tok::l_paren,
12431243
tok::identifier, tok::l_square, tok::kw_Any,
12441244
tok::kw_Self, tok::kw__, tok::kw_var,
1245-
tok::kw_let))
1245+
tok::kw_let, tok::code_complete))
12461246
return true;
12471247

12481248
if (next.is(tok::oper_prefix) && next.getText() == "~")
@@ -1619,6 +1619,11 @@ class Parser {
16191619
/// Whether we are at the start of a parameter name when parsing a parameter.
16201620
bool startsParameterName(bool isClosure);
16211621

1622+
/// Attempts to perform code completion for the possible start of a function
1623+
/// parameter type, returning the source location of the consumed completion
1624+
/// token, or a null location if there is no completion token.
1625+
SourceLoc tryCompleteFunctionParamTypeBeginning();
1626+
16221627
/// Parse a parameter-clause.
16231628
///
16241629
/// \verbatim

lib/Parse/ParsePattern.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,27 @@ bool Parser::startsParameterName(bool isClosure) {
172172
return isClosure;
173173
}
174174

175+
SourceLoc Parser::tryCompleteFunctionParamTypeBeginning() {
176+
if (!L->isCodeCompletion())
177+
return SourceLoc();
178+
179+
// Skip over any starting parameter specifiers.
180+
{
181+
CancellableBacktrackingScope backtrack(*this);
182+
ParsedTypeAttributeList attrs;
183+
attrs.parse(*this);
184+
if (!Tok.is(tok::code_complete))
185+
return SourceLoc();
186+
187+
backtrack.cancelBacktrack();
188+
}
189+
190+
if (CodeCompletionCallbacks)
191+
CodeCompletionCallbacks->completeTypePossibleFunctionParamBeginning();
192+
193+
return consumeToken(tok::code_complete);
194+
}
195+
175196
ParserStatus
176197
Parser::parseParameterClause(SourceLoc &leftParenLoc,
177198
SmallVectorImpl<ParsedParameter> &params,
@@ -378,14 +399,11 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
378399
// Currently none of the parameter type completions are relevant for
379400
// enum cases, so don't include them. We'll complete for a regular type
380401
// beginning instead.
381-
if (Tok.is(tok::code_complete) &&
382-
paramContext != ParameterContextKind::EnumElement) {
383-
if (CodeCompletionCallbacks)
384-
CodeCompletionCallbacks->completeTypePossibleFunctionParamBeginning();
385-
386-
auto CCLoc = consumeToken(tok::code_complete);
387-
auto *ET = ErrorTypeRepr::create(Context, CCLoc);
388-
return makeParserCodeCompletionResult<TypeRepr>(ET);
402+
if (paramContext != ParameterContextKind::EnumElement) {
403+
if (auto CCLoc = tryCompleteFunctionParamTypeBeginning()) {
404+
auto *ET = ErrorTypeRepr::create(Context, CCLoc);
405+
return makeParserCodeCompletionResult<TypeRepr>(ET);
406+
}
389407
}
390408
return parseType(diag::expected_parameter_type);
391409
};

lib/Parse/ParseType.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,15 +1206,10 @@ ParserResult<TypeRepr> Parser::parseTypeTupleBody() {
12061206
}
12071207
Backtracking.reset();
12081208

1209-
// If we have a code completion token, treat this as a possible parameter
1210-
// type since the user may be writing this as a function type.
1211-
if (Tok.is(tok::code_complete)) {
1212-
if (CodeCompletionCallbacks)
1213-
CodeCompletionCallbacks->completeTypePossibleFunctionParamBeginning();
1214-
1215-
consumeToken();
1209+
// Try complete the start of a parameter type since the user may be writing
1210+
// this as a function type.
1211+
if (tryCompleteFunctionParamTypeBeginning())
12161212
return makeParserCodeCompletionStatus();
1217-
}
12181213

12191214
// Parse the type annotation.
12201215
auto type = parseType(diag::expected_type);

test/IDE/complete_param_specifier.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22

33
func foo(x: #^FUNC_PARAM?check=SPECIFIER^#) {
44
let fn1 = { (x: #CLOSURE_PARAM?check=SPECIFIER#) in }
5-
let fn2: (#^CLOSURE_PARAM_TY_COMPLETE?check=SPECIFIER^#) -> Void
6-
let fn3: (#^CLOSURE_PARAM_TY_INCOMPLETE?check=SPECIFIER^#
5+
let fn2 = { (x: consuming #CLOSURE_PARAM2?check=SPECIFIER#) in }
6+
let fn3: (#^CLOSURE_PARAM_TY_COMPLETE?check=SPECIFIER^#) -> Void
7+
let fn4: (borrowing #^CLOSURE_PARAM_TY_COMPLETE2?check=SPECIFIER^#) -> Void
8+
let fn5: (#^CLOSURE_PARAM_TY_INCOMPLETE?check=SPECIFIER^#
9+
let fn6: (inout #^CLOSURE_PARAM_TY_INCOMPLETE2?check=SPECIFIER^#
710
}
811

12+
func bar(_ x: borrowing #^FUNC_PARAM_2?check=SPECIFIER^#) {}
13+
914
struct S {
1015
init(x: #^INIT_PARAM?check=SPECIFIER^#) {}
1116
subscript(x: #SUBSCRIPT_PARAM?check=SPECIFIER#) {}

0 commit comments

Comments
 (0)