Skip to content

Commit 3d57297

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 25dedc8 commit 3d57297

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
@@ -1238,7 +1238,7 @@ class Parser {
12381238
if (next.isAny(tok::at_sign, tok::kw_inout, tok::l_paren,
12391239
tok::identifier, tok::l_square, tok::kw_Any,
12401240
tok::kw_Self, tok::kw__, tok::kw_var,
1241-
tok::kw_let))
1241+
tok::kw_let, tok::code_complete))
12421242
return true;
12431243

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

1611+
/// Attempts to perform code completion for the possible start of a function
1612+
/// parameter type, returning the source location of the consumed completion
1613+
/// token, or a null location if there is no completion token.
1614+
SourceLoc tryCompleteFunctionParamTypeBeginning();
1615+
16111616
/// Parse a parameter-clause.
16121617
///
16131618
/// \verbatim

lib/Parse/ParsePattern.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,27 @@ bool Parser::startsParameterName(bool isClosure) {
154154
return isClosure;
155155
}
156156

157+
SourceLoc Parser::tryCompleteFunctionParamTypeBeginning() {
158+
if (!L->isCodeCompletion())
159+
return SourceLoc();
160+
161+
// Skip over any starting parameter specifiers.
162+
{
163+
CancellableBacktrackingScope backtrack(*this);
164+
ParsedTypeAttributeList attrs;
165+
attrs.parse(*this);
166+
if (!Tok.is(tok::code_complete))
167+
return SourceLoc();
168+
169+
backtrack.cancelBacktrack();
170+
}
171+
172+
if (CodeCompletionCallbacks)
173+
CodeCompletionCallbacks->completeTypePossibleFunctionParamBeginning();
174+
175+
return consumeToken(tok::code_complete);
176+
}
177+
157178
ParserStatus
158179
Parser::parseParameterClause(SourceLoc &leftParenLoc,
159180
SmallVectorImpl<ParsedParameter> &params,
@@ -360,14 +381,11 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
360381
// Currently none of the parameter type completions are relevant for
361382
// enum cases, so don't include them. We'll complete for a regular type
362383
// beginning instead.
363-
if (Tok.is(tok::code_complete) &&
364-
paramContext != ParameterContextKind::EnumElement) {
365-
if (CodeCompletionCallbacks)
366-
CodeCompletionCallbacks->completeTypePossibleFunctionParamBeginning();
367-
368-
auto CCLoc = consumeToken(tok::code_complete);
369-
auto *ET = ErrorTypeRepr::create(Context, CCLoc);
370-
return makeParserCodeCompletionResult<TypeRepr>(ET);
384+
if (paramContext != ParameterContextKind::EnumElement) {
385+
if (auto CCLoc = tryCompleteFunctionParamTypeBeginning()) {
386+
auto *ET = ErrorTypeRepr::create(Context, CCLoc);
387+
return makeParserCodeCompletionResult<TypeRepr>(ET);
388+
}
371389
}
372390
return parseType(diag::expected_parameter_type);
373391
};

lib/Parse/ParseType.cpp

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

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

12161211
// Parse the type annotation.
12171212
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)