Skip to content

Commit df60089

Browse files
DougGregortkremenek
authored andcommitted
[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 167e039 commit df60089

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
@@ -1822,7 +1822,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18221822
type = ParamDecl::getVarargBaseTy(type);
18231823

18241824
Builder.addCallParameter(param->getArgumentName(), type,
1825-
param->isVariadic());
1825+
param->isVariadic(), true);
18261826
}
18271827
}
18281828

@@ -1856,7 +1856,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18561856
else if (IsTopLevel)
18571857
Builder.addAnnotatedLeftParen();
18581858
Builder.addCallParameter(Identifier(), PT->getUnderlyingType(),
1859-
/*IsVarArg*/false);
1859+
/*IsVarArg*/false, IsTopLevel);
18601860
if (IsTopLevel)
18611861
Builder.addRightParen();
18621862
return;
@@ -1867,7 +1867,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18671867
else if (IsTopLevel)
18681868
Builder.addAnnotatedLeftParen();
18691869

1870-
Builder.addCallParameter(Label, T, IsVarArg);
1870+
Builder.addCallParameter(Label, T, IsVarArg, IsTopLevel);
18711871
if (IsTopLevel)
18721872
Builder.addRightParen();
18731873
}
@@ -1942,9 +1942,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19421942
if (BodyParams) {
19431943
// If we have a local name for the parameter, pass in that as well.
19441944
auto name = BodyParams->get(i)->getName();
1945-
Builder.addCallParameter(Name, name, ParamType, TupleElt.isVararg());
1945+
Builder.addCallParameter(Name, name, ParamType, TupleElt.isVararg(),
1946+
true);
19461947
} else {
1947-
Builder.addCallParameter(Name, ParamType, TupleElt.isVararg());
1948+
Builder.addCallParameter(Name, ParamType, TupleElt.isVararg(), true);
19481949
}
19491950
modifiedBuilder = true;
19501951
NeedComma = true;
@@ -1961,9 +1962,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19611962
if (BodyParams) {
19621963
auto name = BodyParams->get(0)->getName();
19631964
Builder.addCallParameter(Identifier(), name, T,
1964-
/*IsVarArg*/false);
1965+
/*IsVarArg*/false, true);
19651966
} else
1966-
Builder.addCallParameter(Identifier(), T, /*IsVarArg*/false);
1967+
Builder.addCallParameter(Identifier(), T, /*IsVarArg*/false, true);
19671968
}
19681969

19691970
return modifiedBuilder;
@@ -2122,7 +2123,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
21222123

21232124
Builder.addLeftParen();
21242125
Builder.addCallParameter(Ctx.Id_self, FirstInputType,
2125-
/*IsVarArg*/ false);
2126+
/*IsVarArg*/ false, true);
21262127
Builder.addRightParen();
21272128
} else {
21282129
Builder.addLeftParen();
@@ -2920,7 +2921,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
29202921
builder.addTextChunk(op->getName().str());
29212922
builder.addWhitespace(" ");
29222923
if (RHSType)
2923-
builder.addCallParameter(Identifier(), Identifier(), RHSType, false);
2924+
builder.addCallParameter(Identifier(), Identifier(), RHSType, false,
2925+
true);
29242926
if (resultType)
29252927
addTypeAnnotation(builder, resultType);
29262928
}
@@ -3135,15 +3137,16 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31353137
builder.addTextChunk("#Color");
31363138
builder.addLeftParen();
31373139
builder.addCallParameter(context.getIdentifier("colorLiteralRed"),
3138-
floatType, false);
3140+
floatType, false, true);
31393141
builder.addComma();
31403142
builder.addCallParameter(context.getIdentifier("green"), floatType,
3141-
false);
3143+
false, true);
31423144
builder.addComma();
3143-
builder.addCallParameter(context.getIdentifier("blue"), floatType, false);
3145+
builder.addCallParameter(context.getIdentifier("blue"), floatType,
3146+
false, true);
31443147
builder.addComma();
31453148
builder.addCallParameter(context.getIdentifier("alpha"), floatType,
3146-
false);
3149+
false, true);
31473150
builder.addRightParen();
31483151
builder.addTextChunk("#");
31493152
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)