Skip to content

Commit 83084e2

Browse files
committed
[CodeCompletion] Suggest 'file', 'line', et al. after #
rdar://problem/47169238
1 parent 902c821 commit 83084e2

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
@@ -1479,6 +1479,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
14791479
ASTContext &Ctx;
14801480
LazyResolver *TypeResolver = nullptr;
14811481
const DeclContext *CurrDeclContext;
1482+
ModuleDecl *CurrModule;
14821483
ClangImporter *Importer;
14831484
CodeCompletionContext *CompletionContext;
14841485

@@ -1627,6 +1628,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
16271628
const DeclContext *CurrDeclContext,
16281629
CodeCompletionContext *CompletionContext = nullptr)
16291630
: Sink(Sink), Ctx(Ctx), CurrDeclContext(CurrDeclContext),
1631+
CurrModule(CurrDeclContext ? CurrDeclContext->getParentModule()
1632+
: nullptr),
16301633
Importer(static_cast<ClangImporter *>(CurrDeclContext->getASTContext().
16311634
getClangModuleLoader())),
16321635
CompletionContext(CompletionContext) {
@@ -3511,9 +3514,73 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35113514
addPostfixBang(ValueT);
35123515
}
35133516

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

35183585
auto addFromProto = [&](
35193586
CodeCompletionLiteralKind kind, StringRef defaultTypeName,
@@ -3525,38 +3592,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35253592
builder.setLiteralKind(kind);
35263593

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

35623598
// FIXME: the pedantically correct way is to resolve Swift.*LiteralType.
@@ -3705,8 +3741,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
37053741
});
37063742
}
37073743

3708-
if (LiteralCompletions)
3744+
if (LiteralCompletions) {
37093745
addValueLiteralCompletions();
3746+
addPoundLiteralCompletions(/*needPound=*/true);
3747+
}
3748+
37103749

37113750
// If the expected type is ObjectiveC.Selector, add #selector. If
37123751
// it's String, add #keyPath.
@@ -4839,14 +4878,6 @@ static void addExprKeywords(CodeCompletionResultSink &Sink) {
48394878
addKeyword(Sink, "try", CodeCompletionKeywordKind::kw_try);
48404879
addKeyword(Sink, "try!", CodeCompletionKeywordKind::kw_try);
48414880
addKeyword(Sink, "try?", CodeCompletionKeywordKind::kw_try);
4842-
// FIXME: The pedantically correct way to find the type is to resolve the
4843-
// Swift.StringLiteralType type.
4844-
addKeyword(Sink, "#function", CodeCompletionKeywordKind::pound_function, "String");
4845-
addKeyword(Sink, "#file", CodeCompletionKeywordKind::pound_file, "String");
4846-
// Same: Swift.IntegerLiteralType.
4847-
addKeyword(Sink, "#line", CodeCompletionKeywordKind::pound_line, "Int");
4848-
addKeyword(Sink, "#column", CodeCompletionKeywordKind::pound_column, "Int");
4849-
addKeyword(Sink, "#dsohandle", CodeCompletionKeywordKind::pound_dsohandle, "UnsafeMutableRawPointer");
48504881
}
48514882

48524883
static void addOpaqueTypeKeyword(CodeCompletionResultSink &Sink) {
@@ -5445,7 +5476,12 @@ void CodeCompletionCallbacksImpl::doneParsing() {
54455476
}
54465477

54475478
case CompletionKind::AfterPoundExpr: {
5479+
ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
5480+
Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
5481+
ContextInfo.isSingleExpressionBody());
5482+
54485483
Lookup.addPoundAvailable(ParentStmtKind);
5484+
Lookup.addPoundLiteralCompletions(/*needPound=*/false);
54495485
Lookup.addPoundSelector(/*needPound=*/false);
54505486
Lookup.addPoundKeyPath(/*needPound=*/false);
54515487
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)