Skip to content

Commit f1aac08

Browse files
committed
[Code completion] Only escape var/let/inout in call argument lists.
Argument labels don't need to be escaped in calls, so don't escape them in code completions for calls. Fixes <rdar://problem/24460721>.
1 parent 1bf1b84 commit f1aac08

File tree

3 files changed

+49
-32
lines changed

3 files changed

+49
-32
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,7 +1817,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18171817
type = ParamDecl::getVarargBaseTy(type);
18181818

18191819
Builder.addCallParameter(param->getArgumentName(), type,
1820-
param->isVariadic());
1820+
param->isVariadic(), true);
18211821
}
18221822
}
18231823

@@ -1851,7 +1851,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18511851
else if (IsTopLevel)
18521852
Builder.addAnnotatedLeftParen();
18531853
Builder.addCallParameter(Identifier(), PT->getUnderlyingType(),
1854-
/*IsVarArg*/false);
1854+
/*IsVarArg*/false, IsTopLevel);
18551855
if (IsTopLevel)
18561856
Builder.addRightParen();
18571857
return;
@@ -1862,7 +1862,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18621862
else if (IsTopLevel)
18631863
Builder.addAnnotatedLeftParen();
18641864

1865-
Builder.addCallParameter(Label, T, IsVarArg);
1865+
Builder.addCallParameter(Label, T, IsVarArg, IsTopLevel);
18661866
if (IsTopLevel)
18671867
Builder.addRightParen();
18681868
}
@@ -1937,9 +1937,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19371937
if (BodyParams) {
19381938
// If we have a local name for the parameter, pass in that as well.
19391939
auto name = BodyParams->get(i)->getName();
1940-
Builder.addCallParameter(Name, name, ParamType, TupleElt.isVararg());
1940+
Builder.addCallParameter(Name, name, ParamType, TupleElt.isVararg(),
1941+
true);
19411942
} else {
1942-
Builder.addCallParameter(Name, ParamType, TupleElt.isVararg());
1943+
Builder.addCallParameter(Name, ParamType, TupleElt.isVararg(), true);
19431944
}
19441945
modifiedBuilder = true;
19451946
NeedComma = true;
@@ -1956,9 +1957,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19561957
if (BodyParams) {
19571958
auto name = BodyParams->get(0)->getName();
19581959
Builder.addCallParameter(Identifier(), name, T,
1959-
/*IsVarArg*/false);
1960+
/*IsVarArg*/false, true);
19601961
} else
1961-
Builder.addCallParameter(Identifier(), T, /*IsVarArg*/false);
1962+
Builder.addCallParameter(Identifier(), T, /*IsVarArg*/false, true);
19621963
}
19631964

19641965
return modifiedBuilder;
@@ -2114,7 +2115,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
21142115

21152116
Builder.addLeftParen();
21162117
Builder.addCallParameter(Ctx.Id_self, FirstInputType,
2117-
/*IsVarArg*/ false);
2118+
/*IsVarArg*/ false, true);
21182119
Builder.addRightParen();
21192120
} else {
21202121
Builder.addLeftParen();
@@ -2863,7 +2864,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28632864
builder.addTextChunk(op->getName().str());
28642865
builder.addWhitespace(" ");
28652866
if (RHSType)
2866-
builder.addCallParameter(Identifier(), Identifier(), RHSType, false);
2867+
builder.addCallParameter(Identifier(), Identifier(), RHSType, false,
2868+
true);
28672869
if (resultType)
28682870
addTypeAnnotation(builder, resultType);
28692871
}
@@ -3078,15 +3080,16 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
30783080
builder.addTextChunk("#Color");
30793081
builder.addLeftParen();
30803082
builder.addCallParameter(context.getIdentifier("colorLiteralRed"),
3081-
floatType, false);
3083+
floatType, false, true);
30823084
builder.addComma();
30833085
builder.addCallParameter(context.getIdentifier("green"), floatType,
3084-
false);
3086+
false, true);
30853087
builder.addComma();
3086-
builder.addCallParameter(context.getIdentifier("blue"), floatType, false);
3088+
builder.addCallParameter(context.getIdentifier("blue"), floatType,
3089+
false, true);
30873090
builder.addComma();
30883091
builder.addCallParameter(context.getIdentifier("alpha"), floatType,
3089-
false);
3092+
false, true);
30903093
builder.addRightParen();
30913094
builder.addTextChunk("#");
30923095
builder.addRightBracket();

lib/IDE/CodeCompletionResultBuilder.h

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "swift/IDE/CodeCompletion.h"
1717
#include "swift/Basic/LLVM.h"
18+
#include "swift/Basic/StringExtras.h"
1819
#include "llvm/ADT/SmallVector.h"
1920
#include "llvm/ADT/StringRef.h"
2021

@@ -247,16 +248,26 @@ class CodeCompletionResultBuilder {
247248
addTypeAnnotation(Annotation);
248249
}
249250

250-
bool escapeKeyword(StringRef Word, llvm::SmallString<16> &EscapedKeyword) {
251-
#define KEYWORD(kw) \
252-
if (Word.equals(#kw)) { \
253-
EscapedKeyword.append("`"); \
254-
EscapedKeyword.append(Word); \
255-
EscapedKeyword.append("`"); \
256-
return true; \
257-
}
251+
StringRef escapeArgumentLabel(StringRef Word,
252+
bool escapeAllKeywords,
253+
llvm::SmallString<16> &EscapedKeyword) {
254+
bool shouldEscape = false;
255+
if (escapeAllKeywords) {
256+
#define KEYWORD(kw) .Case(#kw, true)
257+
shouldEscape = llvm::StringSwitch<bool>(Word)
258258
#include "swift/Parse/Tokens.def"
259-
return false;
259+
.Default(false);
260+
} else {
261+
shouldEscape = !canBeArgumentLabel(Word);
262+
}
263+
264+
if (!shouldEscape)
265+
return Word;
266+
267+
EscapedKeyword.append("`");
268+
EscapedKeyword.append(Word);
269+
EscapedKeyword.append("`");
270+
return EscapedKeyword;
260271
}
261272

262273
void addCallParameterColon() {
@@ -285,7 +296,7 @@ class CodeCompletionResultBuilder {
285296
}
286297

287298
void addCallParameter(Identifier Name, Identifier LocalName, Type Ty,
288-
bool IsVarArg) {
299+
bool IsVarArg, bool Outermost) {
289300
CurrentNestingLevel++;
290301

291302
addSimpleChunk(CodeCompletionString::Chunk::ChunkKind::CallParameterBegin);
@@ -301,8 +312,9 @@ class CodeCompletionResultBuilder {
301312
addChunkWithText(
302313
CodeCompletionString::Chunk::ChunkKind::CallParameterName,
303314
// if the name is not annotation, we need to escape keyword
304-
!IsAnnotation && escapeKeyword(NameStr, EscapedKeyword) ?
305-
EscapedKeyword.str() : NameStr);
315+
IsAnnotation ? NameStr
316+
: escapeArgumentLabel(NameStr, !Outermost,
317+
EscapedKeyword));
306318
if (IsAnnotation)
307319
getLastChunk().setIsAnnotation();
308320

@@ -324,8 +336,7 @@ class CodeCompletionResultBuilder {
324336
// Use local (non-API) parameter name if we have nothing else.
325337
addChunkWithText(
326338
CodeCompletionString::Chunk::ChunkKind::CallParameterInternalName,
327-
escapeKeyword(LocalName.str(), EscapedKeyword) ? EscapedKeyword.str()
328-
: LocalName.str());
339+
escapeArgumentLabel(LocalName.str(), !Outermost, EscapedKeyword));
329340
addChunkWithTextNoCopy(
330341
CodeCompletionString::Chunk::ChunkKind::CallParameterColon, ": ");
331342
}
@@ -364,8 +375,9 @@ class CodeCompletionResultBuilder {
364375
CurrentNestingLevel--;
365376
}
366377

367-
void addCallParameter(Identifier Name, Type Ty, bool IsVarArg) {
368-
addCallParameter(Name, Identifier(), Ty, IsVarArg);
378+
void addCallParameter(Identifier Name, Type Ty, bool IsVarArg,
379+
bool Outermost) {
380+
addCallParameter(Name, Identifier(), Ty, IsVarArg, Outermost);
369381
}
370382

371383
void addGenericParameter(StringRef Name) {

test/IDE/complete_vararg.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class C {
2323
func method4(`do` `do` : Int...) {}
2424
func method5(`class` : Int...) {}
2525
func method6(`class` `protocol`: Int...) {}
26+
func method7(`inout` value: Int...) {}
2627
subscript(i: Int...) -> Int { return 0 }
2728
}
2829

@@ -48,9 +49,10 @@ func testObjDot1() {
4849
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method1({#x: Int...#})[#Void#]{{; name=.+$}}
4950
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method2({#x: Int#}, {#y: Int...#})[#Void#]{{; name=.+$}}
5051
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method3({#w: Int...#})[#(x: Int...) -> Void#]{{; name=.+$}}
51-
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method4({#`do`: Int...#})[#Void#]{{; name=.+$}}
52-
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method5({#(`class`): Int...#})[#Void#]{{; name=.+$}}
53-
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method6({#`class`: Int...#})[#Void#]{{; name=.+$}}
52+
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method4({#do: Int...#})[#Void#]{{; name=.+$}}
53+
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method5({#(class): Int...#})[#Void#]{{; name=.+$}}
54+
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method6({#class: Int...#})[#Void#]{{; name=.+$}}
55+
// OBJ_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: method7({#`inout`: Int...#})[#Void#]{{; name=.+$}}
5456
// OBJ_DOT_1: End completions
5557

5658
func testFreeFunc() {

0 commit comments

Comments
 (0)