Skip to content

Commit 9d75e3f

Browse files
authored
Merge pull request swiftlang#74656 from hamishknight/sending-completion-6.0
[6.0] [Completion] Add completion for `sending` specifier
2 parents 4acfb23 + c90b23b commit 9d75e3f

File tree

6 files changed

+94
-53
lines changed

6 files changed

+94
-53
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/IDE/CodeCompletion.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,10 +1072,14 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
10721072
addKeyword(Sink, "consuming", CodeCompletionKeywordKind::None);
10731073
addKeyword(Sink, "isolated", CodeCompletionKeywordKind::None);
10741074
LLVM_FALLTHROUGH;
1075+
case CompletionKind::TypeDeclResultBeginning:
1076+
addKeyword(Sink, "sending", CodeCompletionKeywordKind::None);
1077+
LLVM_FALLTHROUGH;
10751078
case CompletionKind::TypeBeginning:
1076-
addKeyword(Sink, "repeat", CodeCompletionKeywordKind::None);
1079+
// Not technically allowed after '->', since you need to write in parens.
1080+
if (Kind != CompletionKind::TypeDeclResultBeginning)
1081+
addKeyword(Sink, "repeat", CodeCompletionKeywordKind::None);
10771082
LLVM_FALLTHROUGH;
1078-
case CompletionKind::TypeDeclResultBeginning:
10791083
case CompletionKind::TypeSimpleOrComposition:
10801084
addKeyword(Sink, "some", CodeCompletionKeywordKind::None);
10811085
addKeyword(Sink, "any", CodeCompletionKeywordKind::None);

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_ownership_specifier.swift

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %batch-code-completion
2+
3+
func foo(x: #^FUNC_PARAM?check=SPECIFIER^#) {
4+
let fn1 = { (x: #CLOSURE_PARAM?check=SPECIFIER#) in }
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^#
10+
}
11+
12+
func bar(_ x: borrowing #^FUNC_PARAM_2?check=SPECIFIER^#) {}
13+
14+
struct S {
15+
init(x: #^INIT_PARAM?check=SPECIFIER^#) {}
16+
subscript(x: #SUBSCRIPT_PARAM?check=SPECIFIER#) -> #^SUBSCRIPT_RET?check=RESULT;check=RESULT_NOT^# {}
17+
}
18+
19+
// Don't complete for enum cases.
20+
enum E {
21+
case e(#^ENUM_CASE_TY?check=SPECIFIER_NOT^#)
22+
case f(x: #^ENUM_CASE_LABELED_TY?check=SPECIFIER_NOT^#)
23+
}
24+
25+
// Don't complete the parameter specifiers for a variable type.
26+
//
27+
// Note that we will still complete 'sending' here, even though it isn't
28+
// currently supported for computed properties (it is supported for functions
29+
// and subscripts though).
30+
let x: #^VAR_TY?check=RESULT;check=RESULT_NOT^#
31+
var y: #^VAR_TY2?check=RESULT;check=RESULT_NOT^#
32+
33+
// Or for a return type.
34+
func bar() -> #^RESULT_TY?check=RESULT;check=RESULT_NOT^# {}
35+
36+
// SPECIFIER-DAG: Keyword[inout]/None: inout; name=inout
37+
// SPECIFIER-DAG: Keyword/None: consuming; name=consuming
38+
// SPECIFIER-DAG: Keyword/None: borrowing; name=borrowing
39+
// SPECIFIER-DAG: Keyword/None: isolated; name=isolated
40+
// SPECIFIER-DAG: Keyword/None: sending; name=sending
41+
42+
// SPECIFIER_NOT-NOT: Keyword[inout]/None: inout
43+
// SPECIFIER_NOT-NOT: Keyword/None: consuming
44+
// SPECIFIER_NOT-NOT: Keyword/None: borrowing
45+
// SPECIFIER_NOT-NOT: Keyword/None: isolated
46+
// SPECIFIER_NOT-NOT: Keyword/None: sending
47+
48+
// RESULT_NOT-NOT: Keyword[inout]/None: inout
49+
// RESULT_NOT-NOT: Keyword/None: consuming
50+
// RESULT_NOT-NOT: Keyword/None: borrowing
51+
// RESULT_NOT-NOT: Keyword/None: isolated
52+
53+
// RESULT-DAG: Keyword/None: sending

0 commit comments

Comments
 (0)