Skip to content

Commit a3e3d3e

Browse files
committed
[CodeCompletion] Suggest 'file', 'line', et al. after #
rdar://problem/47169238 (cherry picked from commit 83084e2)
1 parent 1fef066 commit a3e3d3e

File tree

4 files changed

+98
-57
lines changed

4 files changed

+98
-57
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 78 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
14811481
ASTContext &Ctx;
14821482
LazyResolver *TypeResolver = nullptr;
14831483
const DeclContext *CurrDeclContext;
1484+
ModuleDecl *CurrModule;
14841485
ClangImporter *Importer;
14851486
CodeCompletionContext *CompletionContext;
14861487

@@ -1629,6 +1630,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
16291630
const DeclContext *CurrDeclContext,
16301631
CodeCompletionContext *CompletionContext = nullptr)
16311632
: Sink(Sink), Ctx(Ctx), CurrDeclContext(CurrDeclContext),
1633+
CurrModule(CurrDeclContext ? CurrDeclContext->getParentModule()
1634+
: nullptr),
16321635
Importer(static_cast<ClangImporter *>(CurrDeclContext->getASTContext().
16331636
getClangModuleLoader())),
16341637
CompletionContext(CompletionContext) {
@@ -3514,9 +3517,73 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35143517
addPostfixBang(ValueT);
35153518
}
35163519

3520+
void addTypeRelationFromProtocol(CodeCompletionResultBuilder &builder,
3521+
CodeCompletionLiteralKind kind,
3522+
StringRef defaultTypeName) {
3523+
// Check for matching ExpectedTypes.
3524+
auto *P = Ctx.getProtocol(protocolForLiteralKind(kind));
3525+
for (auto T : expectedTypeContext.possibleTypes) {
3526+
if (!T)
3527+
continue;
3528+
3529+
auto typeRelation = CodeCompletionResult::Identical;
3530+
// Convert through optional types unless we're looking for a protocol
3531+
// that Optional itself conforms to.
3532+
if (kind != CodeCompletionLiteralKind::NilLiteral) {
3533+
if (auto optionalObjT = T->getOptionalObjectType()) {
3534+
T = optionalObjT;
3535+
typeRelation = CodeCompletionResult::Convertible;
3536+
}
3537+
}
3538+
3539+
// Check for conformance to the literal protocol.
3540+
if (auto *NTD = T->getAnyNominal()) {
3541+
SmallVector<ProtocolConformance *, 2> conformances;
3542+
if (NTD->lookupConformance(CurrModule, P, conformances)) {
3543+
addTypeAnnotation(builder, T);
3544+
builder.setExpectedTypeRelation(typeRelation);
3545+
return;
3546+
}
3547+
}
3548+
}
3549+
3550+
// Fallback to showing the default type.
3551+
if (!defaultTypeName.empty())
3552+
builder.addTypeAnnotation(defaultTypeName);
3553+
}
3554+
3555+
/// Add '#file', '#line', et at.
3556+
void addPoundLiteralCompletions(bool needPound) {
3557+
auto addFromProto = [&](StringRef name, CodeCompletionKeywordKind kwKind,
3558+
CodeCompletionLiteralKind literalKind,
3559+
StringRef defaultTypeName) {
3560+
if (!needPound)
3561+
name = name.substr(1);
3562+
3563+
CodeCompletionResultBuilder builder(
3564+
Sink, CodeCompletionResult::ResultKind::Keyword,
3565+
SemanticContextKind::None, {});
3566+
builder.setLiteralKind(literalKind);
3567+
builder.setKeywordKind(kwKind);
3568+
builder.addTextChunk(name);
3569+
addTypeRelationFromProtocol(builder, literalKind, defaultTypeName);
3570+
};
3571+
3572+
addFromProto("#function", CodeCompletionKeywordKind::pound_function,
3573+
CodeCompletionLiteralKind::StringLiteral, "String");
3574+
addFromProto("#file", CodeCompletionKeywordKind::pound_file,
3575+
CodeCompletionLiteralKind::StringLiteral, "String");
3576+
addFromProto("#line", CodeCompletionKeywordKind::pound_line,
3577+
CodeCompletionLiteralKind::IntegerLiteral, "Int");
3578+
addFromProto("#column", CodeCompletionKeywordKind::pound_column,
3579+
CodeCompletionLiteralKind::IntegerLiteral, "Int");
3580+
3581+
addKeyword(needPound ? "#dsohandle" : "dsohandle", "UnsafeRawPointer",
3582+
CodeCompletionKeywordKind::pound_dsohandle);
3583+
}
3584+
35173585
void addValueLiteralCompletions() {
35183586
auto &context = CurrDeclContext->getASTContext();
3519-
auto *module = CurrDeclContext->getParentModule();
35203587

35213588
auto addFromProto = [&](
35223589
CodeCompletionLiteralKind kind, StringRef defaultTypeName,
@@ -3528,38 +3595,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35283595
builder.setLiteralKind(kind);
35293596

35303597
consumer(builder);
3531-
3532-
// Check for matching ExpectedTypes.
3533-
auto *P = context.getProtocol(protocolForLiteralKind(kind));
3534-
bool foundConformance = false;
3535-
for (auto T : expectedTypeContext.possibleTypes) {
3536-
if (!T)
3537-
continue;
3538-
3539-
auto typeRelation = CodeCompletionResult::Identical;
3540-
// Convert through optional types unless we're looking for a protocol
3541-
// that Optional itself conforms to.
3542-
if (kind != CodeCompletionLiteralKind::NilLiteral) {
3543-
if (auto optionalObjT = T->getOptionalObjectType()) {
3544-
T = optionalObjT;
3545-
typeRelation = CodeCompletionResult::Convertible;
3546-
}
3547-
}
3548-
3549-
// Check for conformance to the literal protocol.
3550-
if (auto *NTD = T->getAnyNominal()) {
3551-
SmallVector<ProtocolConformance *, 2> conformances;
3552-
if (NTD->lookupConformance(module, P, conformances)) {
3553-
foundConformance = true;
3554-
addTypeAnnotation(builder, T);
3555-
builder.setExpectedTypeRelation(typeRelation);
3556-
}
3557-
}
3558-
}
3559-
3560-
// Fallback to showing the default type.
3561-
if (!foundConformance && !defaultTypeName.empty())
3562-
builder.addTypeAnnotation(defaultTypeName);
3598+
addTypeRelationFromProtocol(builder, kind, defaultTypeName);
35633599
};
35643600

35653601
// FIXME: the pedantically correct way is to resolve Swift.*LiteralType.
@@ -3708,8 +3744,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
37083744
});
37093745
}
37103746

3711-
if (LiteralCompletions)
3747+
if (LiteralCompletions) {
37123748
addValueLiteralCompletions();
3749+
addPoundLiteralCompletions(/*needPound=*/true);
3750+
}
3751+
37133752

37143753
// If the expected type is ObjectiveC.Selector, add #selector. If
37153754
// it's String, add #keyPath.
@@ -4842,14 +4881,6 @@ static void addExprKeywords(CodeCompletionResultSink &Sink) {
48424881
addKeyword(Sink, "try", CodeCompletionKeywordKind::kw_try);
48434882
addKeyword(Sink, "try!", CodeCompletionKeywordKind::kw_try);
48444883
addKeyword(Sink, "try?", CodeCompletionKeywordKind::kw_try);
4845-
// FIXME: The pedantically correct way to find the type is to resolve the
4846-
// Swift.StringLiteralType type.
4847-
addKeyword(Sink, "#function", CodeCompletionKeywordKind::pound_function, "String");
4848-
addKeyword(Sink, "#file", CodeCompletionKeywordKind::pound_file, "String");
4849-
// Same: Swift.IntegerLiteralType.
4850-
addKeyword(Sink, "#line", CodeCompletionKeywordKind::pound_line, "Int");
4851-
addKeyword(Sink, "#column", CodeCompletionKeywordKind::pound_column, "Int");
4852-
addKeyword(Sink, "#dsohandle", CodeCompletionKeywordKind::pound_dsohandle, "UnsafeMutableRawPointer");
48534884
}
48544885

48554886
static void addOpaqueTypeKeyword(CodeCompletionResultSink &Sink) {
@@ -5448,7 +5479,12 @@ void CodeCompletionCallbacksImpl::doneParsing() {
54485479
}
54495480

54505481
case CompletionKind::AfterPoundExpr: {
5482+
ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
5483+
Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
5484+
ContextInfo.isSingleExpressionBody());
5485+
54515486
Lookup.addPoundAvailable(ParentStmtKind);
5487+
Lookup.addPoundLiteralCompletions(/*needPound=*/false);
54525488
Lookup.addPoundSelector(/*needPound=*/false);
54535489
Lookup.addPoundKeyPath(/*needPound=*/false);
54545490
break;

test/IDE/complete_expr_postfix_begin.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,10 @@ typealias FooTypealias = Int
128128
// COMMON-DAG: Decl[Struct]/OtherModule[Swift]: Int32[#Int32#]{{; name=.+$}}
129129
// COMMON-DAG: Decl[Struct]/OtherModule[Swift]: Int64[#Int64#]{{; name=.+$}}
130130
// COMMON-DAG: Decl[Struct]/OtherModule[Swift]: Bool[#Bool#]{{; name=.+$}}
131-
// COMMON-DAG: Keyword[#function]/None: #function[#String#]{{; name=.+$}}
132-
// COMMON-DAG: Keyword[#file]/None: #file[#String#]{{; name=.+$}}
133-
// COMMON-DAG: Keyword[#line]/None: #line[#Int#]{{; name=.+$}}
134-
// COMMON-DAG: Keyword[#column]/None: #column[#Int#]{{; name=.+$}}
131+
// COMMON-DAG: Keyword[#function]/None{{(/TypeRelation\[Identical\])?}}: #function[#String#]{{; name=.+$}}
132+
// COMMON-DAG: Keyword[#file]/None{{(/TypeRelation\[Identical\])?}}: #file[#String#]{{; name=.+$}}
133+
// COMMON-DAG: Keyword[#line]/None{{(/TypeRelation\[Identical\])?}}: #line[#Int#]{{; name=.+$}}
134+
// COMMON-DAG: Keyword[#column]/None{{(/TypeRelation\[Identical\])?}}: #column[#Int#]{{; name=.+$}}
135135
// COMMON: End completions
136136

137137
// NO_SELF-NOT: {{[[:<:]][Ss]elf[[:>:]]}}

test/IDE/complete_keywords.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,10 @@
191191
// KW_DECL_STMT-DAG: Keyword[try]/None: try{{; name=.+$}}
192192
// KW_DECL_STMT-DAG: Keyword[try]/None: try!{{; name=.+$}}
193193
// KW_DECL_STMT-DAG: Keyword[try]/None: try?{{; name=.+$}}
194-
// KW_DECL_STMT-DAG: Keyword[#function]/None: #function[#String#]{{; name=.+$}}
195-
// KW_DECL_STMT-DAG: Keyword[#file]/None: #file[#String#]{{; name=.+$}}
196-
// KW_DECL_STMT-DAG: Keyword[#line]/None: #line[#Int#]{{; name=.+$}}
197-
// KW_DECL_STMT-DAG: Keyword[#column]/None: #column[#Int#]{{; name=.+$}}
194+
// KW_DECL_STMT-DAG: Keyword[#function]/None{{(/TypeRelation\[Identical\])?}}: #function[#String#]{{; name=.+$}}
195+
// KW_DECL_STMT-DAG: Keyword[#file]/None{{(/TypeRelation\[Identical\])?}}: #file[#String#]{{; name=.+$}}
196+
// KW_DECL_STMT-DAG: Keyword[#line]/None{{(/TypeRelation\[Identical\])?}}: #line[#Int#]{{; name=.+$}}
197+
// KW_DECL_STMT-DAG: Keyword[#column]/None{{(/TypeRelation\[Identical\])?}}: #column[#Int#]{{; name=.+$}}
198198
//
199199
// Literals
200200
//
@@ -211,10 +211,10 @@
211211
// KW_EXPR-DAG: Keyword[try]/None: try{{; name=.+$}}
212212
// KW_EXPR-DAG: Keyword[try]/None: try!{{; name=.+$}}
213213
// KW_EXPR-DAG: Keyword[try]/None: try?{{; name=.+$}}
214-
// KW_EXPR-DAG: Keyword[#function]/None: #function[#String#]{{; name=.+$}}
215-
// KW_EXPR-DAG: Keyword[#file]/None: #file[#String#]{{; name=.+$}}
216-
// KW_EXPR-DAG: Keyword[#line]/None: #line[#Int#]{{; name=.+$}}
217-
// KW_EXPR-DAG: Keyword[#column]/None: #column[#Int#]{{; name=.+$}}
214+
// KW_EXPR-DAG: Keyword[#function]/None{{(/TypeRelation\[Identical\])?}}: #function[#String#]{{; name=.+$}}
215+
// KW_EXPR-DAG: Keyword[#file]/None{{(/TypeRelation\[Identical\])?}}: #file[#String#]{{; name=.+$}}
216+
// KW_EXPR-DAG: Keyword[#line]/None{{(/TypeRelation\[Identical\])?}}: #line[#Int#]{{; name=.+$}}
217+
// KW_EXPR-DAG: Keyword[#column]/None{{(/TypeRelation\[Identical\])?}}: #column[#Int#]{{; name=.+$}}
218218
//
219219
// let and var
220220
//

test/IDE/complete_pound_expr.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@ func test1() {
77
_ = use(##^POUND_EXPR_1^#)
88
}
99

10-
// POUND_EXPR_STRINGCONTEXT: Begin completions, 2 items
10+
// POUND_EXPR_STRINGCONTEXT: Begin completions, 7 items
1111
// POUND_EXPR_STRINGCONTEXT-NOT: available
12-
// POUND_EXPR_STRINGCONTEXT-DAG: Keyword/ExprSpecific: selector({#@objc method#}); name=selector(@objc method)
13-
// POUND_EXPR_STRINGCONTEXT-DAG: Keyword/ExprSpecific: keyPath({#@objc property sequence#}); name=keyPath(@objc property sequence)
12+
// POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#function]/None/TypeRelation[Identical]: function[#String#];
13+
// POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#file]/None/TypeRelation[Identical]: file[#String#];
14+
// POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#line]/None: line[#Int#];
15+
// POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#column]/None: column[#Int#];
16+
// POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#dsohandle]/None: dsohandle[#UnsafeRawPointer#];
17+
// POUND_EXPR_STRINGCONTEXT-DAG: Keyword/ExprSpecific: selector({#@objc method#});
18+
// POUND_EXPR_STRINGCONTEXT-DAG: Keyword/ExprSpecific: keyPath({#@objc property sequence#});
1419
// POUND_EXPR_STRINGCONTEXT: End completions

0 commit comments

Comments
 (0)