Skip to content

Commit 940e0a0

Browse files
authored
Merge pull request #11057 from benlangmuir/cc-enum-leading-dot-4
[code-completion] Add leading-dot completion for enums
2 parents 18110c6 + 178eb80 commit 940e0a0

File tree

5 files changed

+70
-7
lines changed

5 files changed

+70
-7
lines changed

include/swift/IDE/CodeCompletion.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,10 @@ class CodeCompletionContext {
800800
CompletionKind CodeCompletionKind = CompletionKind::None;
801801
bool HasExpectedTypeRelation = false;
802802

803+
/// Whether there may be members that can use implicit member syntax,
804+
/// e.g. `x = .foo`.
805+
bool MayUseImplicitMemberExpr = false;
806+
803807
CodeCompletionContext(CodeCompletionCache &Cache)
804808
: Cache(Cache) {}
805809

lib/IDE/CodeCompletion.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
15741574
OwnedResolver TypeResolver;
15751575
const DeclContext *CurrDeclContext;
15761576
ClangImporter *Importer;
1577+
CodeCompletionContext *CompletionContext;
15771578

15781579
enum class LookupKind {
15791580
ValueExpr,
@@ -1719,11 +1720,13 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
17191720
public:
17201721
CompletionLookup(CodeCompletionResultSink &Sink,
17211722
ASTContext &Ctx,
1722-
const DeclContext *CurrDeclContext)
1723+
const DeclContext *CurrDeclContext,
1724+
CodeCompletionContext *CompletionContext = nullptr)
17231725
: Sink(Sink), Ctx(Ctx),
17241726
TypeResolver(createLazyResolver(Ctx)), CurrDeclContext(CurrDeclContext),
17251727
Importer(static_cast<ClangImporter *>(CurrDeclContext->getASTContext().
1726-
getClangModuleLoader())) {
1728+
getClangModuleLoader())),
1729+
CompletionContext(CompletionContext) {
17271730

17281731
// Determine if we are doing code completion inside a static method.
17291732
if (CurrDeclContext) {
@@ -3650,6 +3653,19 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
36503653
}
36513654
}
36523655

3656+
if (CompletionContext) {
3657+
// FIXME: this is an awful simplification that says all and only enums can
3658+
// use implicit member syntax (leading dot). Computing the accurate answer
3659+
// using lookup (e.g. getUnresolvedMemberCompletions) is too expensive,
3660+
// and for some clients this approximation is good enough.
3661+
CompletionContext->MayUseImplicitMemberExpr =
3662+
std::any_of(ExpectedTypes.begin(), ExpectedTypes.end(), [](Type T) {
3663+
if (auto *NTD = T->getAnyNominal())
3664+
return isa<EnumDecl>(NTD);
3665+
return false;
3666+
});
3667+
}
3668+
36533669
if (LiteralCompletions)
36543670
addValueLiteralCompletions();
36553671

@@ -5106,7 +5122,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
51065122
return;
51075123

51085124
CompletionLookup Lookup(CompletionContext.getResultSink(), P.Context,
5109-
CurDeclContext);
5125+
CurDeclContext, &CompletionContext);
51105126
if (ExprType) {
51115127
Lookup.setIsStaticMetatype(ParsedExpr->isStaticallyDerivedMetatype());
51125128
}

test/SourceKit/CodeComplete/complete_inner.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,28 @@ func test006() {
144144
// KEYWORD_0-NOT: for_
145145
// KEYWORD_0-NOT: fortest
146146
// KEYWORD_0-NOT: for.
147+
148+
enum E0 {
149+
case case0
150+
}
151+
152+
// RUN: %complete-test %s -group=none -no-inner-results -no-inner-operators -tok=LEADING_DOT_0 | %FileCheck %s -check-prefix=LEADING_NODOT_E0
153+
// RUN: %complete-test %s -group=none -no-inner-results -inner-operators -tok=LEADING_DOT_0 | %FileCheck %s -check-prefix=LEADING_DOT_E0
154+
func test007() {
155+
var e: E0
156+
e = #^LEADING_DOT_0^#
157+
}
158+
// LEADING_NODOT_E0-NOT: .
159+
// LEADING_DOT_E0: .
160+
161+
struct WithLeading {
162+
static var foo: WithLeading = WithLeading()
163+
}
164+
165+
// RUN: %complete-test %s -group=none -no-inner-results -inner-operators -tok=LEADING_DOT_1 | %FileCheck %s -check-prefix=LEADING_DOT_S
166+
func test009() {
167+
var e: WithLeading
168+
e = #^LEADING_DOT_1^#
169+
}
170+
// FIXME: should have leading dot.
171+
// LEADING_DOT_S-NOT: .

tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,10 @@ bool CodeCompletion::SessionCache::getCompletionHasExpectedTypes() {
729729
llvm::sys::ScopedLock L(mtx);
730730
return completionHasExpectedTypes;
731731
}
732+
bool CodeCompletion::SessionCache::getCompletionMayUseImplicitMemberExpr() {
733+
llvm::sys::ScopedLock L(mtx);
734+
return completionMayUseImplicitMemberExpr;
735+
}
732736
const CodeCompletion::FilterRules &
733737
CodeCompletion::SessionCache::getFilterRules() {
734738
llvm::sys::ScopedLock L(mtx);
@@ -1038,6 +1042,12 @@ static void transformAndForwardResults(
10381042
if (!hasEarlyInnerResults) {
10391043
organizer.addCompletionsWithFilter(session->getSortedCompletions(),
10401044
filterText, rules, exactMatch);
1045+
// Add leading dot?
1046+
if (options.addInnerOperators && !rules.hideFilterName(".") &&
1047+
session->getCompletionMayUseImplicitMemberExpr()) {
1048+
organizer.addCompletionsWithFilter(
1049+
buildDot(), filterText, CodeCompletion::FilterRules(), exactMatch);
1050+
}
10411051
}
10421052

10431053
if (hasEarlyInnerResults &&
@@ -1164,12 +1174,15 @@ void SwiftLangSupport::codeCompleteOpen(
11641174

11651175
CompletionKind completionKind = CompletionKind::None;
11661176
bool hasExpectedTypes = false;
1177+
bool mayUseImplicitMemberExpr = false;
11671178

11681179
SwiftCodeCompletionConsumer swiftConsumer(
11691180
[&](MutableArrayRef<CodeCompletionResult *> results,
11701181
SwiftCompletionInfo &info) {
1171-
completionKind = info.completionContext->CodeCompletionKind;
1172-
hasExpectedTypes = info.completionContext->HasExpectedTypeRelation;
1182+
auto &completionCtx = *info.completionContext;
1183+
completionKind = completionCtx.CodeCompletionKind;
1184+
hasExpectedTypes = completionCtx.HasExpectedTypeRelation;
1185+
mayUseImplicitMemberExpr = completionCtx.MayUseImplicitMemberExpr;
11731186
completions =
11741187
extendCompletions(results, sink, info, nameToPopularity, CCOpts);
11751188
});
@@ -1203,7 +1216,8 @@ void SwiftLangSupport::codeCompleteOpen(
12031216
std::vector<std::string> argsCopy(extendedArgs.begin(), extendedArgs.end());
12041217
SessionCacheRef session{new SessionCache(
12051218
std::move(sink), std::move(bufferCopy), std::move(argsCopy),
1206-
completionKind, hasExpectedTypes, std::move(filterRules))};
1219+
completionKind, hasExpectedTypes, mayUseImplicitMemberExpr,
1220+
std::move(filterRules))};
12071221
session->setSortedCompletions(std::move(completions));
12081222

12091223
if (!CCSessions.set(name, offset, session)) {

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,17 +141,20 @@ class SessionCache : public ThreadSafeRefCountedBase<SessionCache> {
141141
std::vector<Completion *> sortedCompletions;
142142
CompletionKind completionKind;
143143
bool completionHasExpectedTypes;
144+
bool completionMayUseImplicitMemberExpr;
144145
FilterRules filterRules;
145146
llvm::sys::Mutex mtx;
146147

147148
public:
148149
SessionCache(CompletionSink &&sink,
149150
std::unique_ptr<llvm::MemoryBuffer> &&buffer,
150151
std::vector<std::string> &&args, CompletionKind completionKind,
151-
bool hasExpectedTypes, FilterRules filterRules)
152+
bool hasExpectedTypes, bool mayUseImplicitMemberExpr,
153+
FilterRules filterRules)
152154
: buffer(std::move(buffer)), args(std::move(args)), sink(std::move(sink)),
153155
completionKind(completionKind),
154156
completionHasExpectedTypes(hasExpectedTypes),
157+
completionMayUseImplicitMemberExpr(mayUseImplicitMemberExpr),
155158
filterRules(std::move(filterRules)) {}
156159
void setSortedCompletions(std::vector<Completion *> &&completions);
157160
ArrayRef<Completion *> getSortedCompletions();
@@ -160,6 +163,7 @@ class SessionCache : public ThreadSafeRefCountedBase<SessionCache> {
160163
const FilterRules &getFilterRules();
161164
CompletionKind getCompletionKind();
162165
bool getCompletionHasExpectedTypes();
166+
bool getCompletionMayUseImplicitMemberExpr();
163167
};
164168
typedef RefPtr<SessionCache> SessionCacheRef;
165169

0 commit comments

Comments
 (0)