Add initializers to postfix-expr code completions

Previously, the only way to get initializers was completing after the
name of the type:
    Foo#^complete_here^#
    Foo(#^or_here^#

And now it will also work in unadorned expressions:
    #^a_top_level_completion^#
    bar(a, #^walked_into_a_bar^#

Unfortunately, not all our clients handle this well yet, so it's
protected by a language option.
    -code-complete-inits-in-postfix-expr

Swift SVN r27275
This commit is contained in:
Ben Langmuir
2015-04-14 14:54:08 +00:00
parent 03d393ef5c
commit f778836934
6 changed files with 194 additions and 5 deletions

View File

@@ -1614,8 +1614,8 @@ public:
addMethodImpl();
}
void addConstructorCall(const ConstructorDecl *CD,
DeclVisibilityKind Reason) {
void addConstructorCall(const ConstructorDecl *CD, DeclVisibilityKind Reason,
Identifier addName = Identifier()) {
foundFunction(CD);
Type MemberType = getTypeOfMember(CD);
AnyFunctionType *ConstructorType = nullptr;
@@ -1631,10 +1631,13 @@ public:
getSemanticContext(CD, Reason));
Builder.setAssociatedDecl(CD);
if (IsSuperRefExpr) {
assert(addName.empty());
assert(isa<ConstructorDecl>(CurrDeclContext) &&
"can call super.init only inside a constructor");
addLeadingDot(Builder);
Builder.addTextChunk("init");
} else if (!addName.empty()) {
Builder.addTextChunk(addName.str());
}
if (MemberType->is<ErrorType>()) {
@@ -1660,6 +1663,24 @@ public:
addConstructorImpl();
}
void addConstructorCallsForType(Type type, Identifier name,
DeclVisibilityKind Reason) {
if (!Ctx.LangOpts.CodeCompleteInitsInPostfixExpr)
return;
assert(CurrDeclContext);
SmallVector<ValueDecl *, 16> initializers;
if (CurrDeclContext->lookupQualified(type, Ctx.Id_init, NL_QualifiedDefault,
TypeResolver.get(), initializers)) {
for (auto *init : initializers) {
if (init->isPrivateStdlibDecl(/*whitelistProtocols*/ false) ||
AvailabilityAttr::isUnavailable(init))
continue;
addConstructorCall(cast<ConstructorDecl>(init), Reason, name);
}
}
}
void addSubscriptCall(const SubscriptDecl *SD, DeclVisibilityKind Reason) {
assert(!HaveDot && "can not add a subscript after a dot");
CodeCompletionResultBuilder Builder(
@@ -1850,16 +1871,22 @@ public:
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
addNominalTypeRef(NTD, Reason);
addConstructorCallsForType(NTD->getType(), NTD->getName(), Reason);
return;
}
if (auto *TAD = dyn_cast<TypeAliasDecl>(D)) {
addTypeAliasRef(TAD, Reason);
addConstructorCallsForType(TAD->getUnderlyingType(), TAD->getName(),
Reason);
return;
}
if (auto *GP = dyn_cast<GenericTypeParamDecl>(D)) {
addGenericTypeParamRef(GP, Reason);
for (auto *protocol : GP->getProtocols())
addConstructorCallsForType(protocol->getType(), GP->getName(),
Reason);
return;
}
@@ -1906,16 +1933,22 @@ public:
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
addNominalTypeRef(NTD, Reason);
addConstructorCallsForType(NTD->getType(), NTD->getName(), Reason);
return;
}
if (auto *TAD = dyn_cast<TypeAliasDecl>(D)) {
addTypeAliasRef(TAD, Reason);
addConstructorCallsForType(TAD->getUnderlyingType(), TAD->getName(),
Reason);
return;
}
if (auto *GP = dyn_cast<GenericTypeParamDecl>(D)) {
addGenericTypeParamRef(GP, Reason);
for (auto *protocol : GP->getProtocols())
addConstructorCallsForType(protocol->getType(), GP->getName(),
Reason);
return;
}
@@ -2890,14 +2923,18 @@ void CodeCompletionCallbacksImpl::doneParsing() {
if (Lookup.RequestedCachedResults) {
// Create helpers for result caching.
auto &SwiftContext = P.Context;
// Use the current SourceFile as the DeclContext so that we can use it to
// perform qualified lookup, and to get the correct visibility for
// @testable imports.
const SourceFile &SF = P.SF;
auto FillCacheCallback =
[&SwiftContext, &SF](CodeCompletionCacheImpl &Cache,
const CodeCompletionCacheImpl::Key &K,
const Module *TheModule) {
auto V = Cache.getResultSinkFor(K);
CompletionLookup Lookup(V->Sink, SwiftContext,
K.ForTestableLookup ? &SF : nullptr);
CompletionLookup Lookup(V->Sink, SwiftContext, &SF);
Lookup.getVisibleDeclsOfModule(TheModule, K.AccessPath,
K.ResultsHaveLeadingDot);
Cache.storeResults(K, V);