Skip to content

Commit 491b691

Browse files
author
Nathan Hawes
committed
[CodeCompletion][NFC] Add doc comments and rename symbols for clarity in the new member completion implementation.
1 parent 3850417 commit 491b691

File tree

5 files changed

+33
-132
lines changed

5 files changed

+33
-132
lines changed

include/swift/Sema/IDETypeChecking.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,34 +64,42 @@ namespace swift {
6464

6565
class DotExprLookup: public CompletionCollector {
6666
struct SolutionInfo {
67-
Type Ty;
68-
ValueDecl* ReferencedDecl;
67+
Type BaseTy;
68+
ValueDecl* BaseDecl;
6969
SmallVector<Type, 4> ExpectedTypes;
7070
bool ExpectsNonVoid;
7171
bool BaseIsStaticMetaType;
72-
bool IsSingleExpressionClosure;
72+
bool IsSingleExpressionBody;
7373
};
7474

7575
SourceLoc DotLoc;
7676
DeclContext *DC;
7777
CodeCompletionExpr *CompletionExpr;
78-
79-
llvm::DenseMap<std::pair<Type, Decl*>, size_t> ResultToIndex;
8078
SmallVector<SolutionInfo, 4> Solutions;
79+
llvm::DenseMap<std::pair<Type, Decl*>, size_t> BaseToSolutionIdx;
8180
bool GotCallback = false;
8281

8382
public:
8483
DotExprLookup(SourceLoc DotLoc, DeclContext *DC,
8584
CodeCompletionExpr *CompletionExpr)
8685
: DotLoc(DotLoc), DC(DC), CompletionExpr(CompletionExpr) {}
8786

87+
/// Lookup the completion members on the base expressions extracted from the
88+
/// solutions seen so far and pass them to the given \c Consumer.
8889
void performLookup(ide::CodeCompletionContext &CompletionCtx,
8990
ide::CodeCompletionConsumer &Consumer,
9091
bool isInSelector) const;
92+
93+
/// True if a solution was passed via the \c sawSolution callback.
9194
bool gotCallback() const { return GotCallback; }
95+
96+
/// Typecheck the code completion expression in isolation, calling
97+
/// \c sawSolution for each solution formed.
9298
void fallbackTypeCheck();
9399

94100
private:
101+
/// Called for each solution produced while type-checking an expression containing a code
102+
/// completion expression.
95103
void sawSolution(const constraints::Solution &solution) override;
96104
};
97105

lib/IDE/CodeCompletion.cpp

Lines changed: 15 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,7 +1716,6 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
17161716
private:
17171717
void addKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody);
17181718
bool trySolverCompletion();
1719-
void deliverCompletionResults();
17201719
};
17211720
} // end anonymous namespace
17221721

@@ -5812,10 +5811,10 @@ static void addConditionalCompilationFlags(ASTContext &Ctx,
58125811
}
58135812
}
58145813

5815-
static void processModuleRequests(CodeCompletionContext &CompletionContext,
5816-
CompletionLookup &Lookup,
5817-
SourceFile &SF,
5818-
CodeCompletionConsumer &Consumer) {
5814+
static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
5815+
CompletionLookup &Lookup,
5816+
SourceFile &SF,
5817+
CodeCompletionConsumer &Consumer) {
58195818
llvm::SmallPtrSet<Identifier, 8> seenModuleNames;
58205819
std::vector<RequestedCachedModule> RequestedModules;
58215820

@@ -5890,7 +5889,6 @@ static void processModuleRequests(CodeCompletionContext &CompletionContext,
58905889

58915890
// Add results for all imported modules.
58925891
SmallVector<ModuleDecl::ImportedModule, 4> Imports;
5893-
//auto *SF = CurDeclContext->getParentSourceFile();
58945892
SF.getImportedModules(
58955893
Imports, {ModuleDecl::ImportFilterKind::Public,
58965894
ModuleDecl::ImportFilterKind::Private,
@@ -5903,7 +5901,11 @@ static void processModuleRequests(CodeCompletionContext &CompletionContext,
59035901
}
59045902
}
59055903
Lookup.RequestedCachedResults.clear();
5904+
CompletionContext.typeContextKind = Lookup.typeContextKind();
59065905

5906+
// Use the current SourceFile as the DeclContext so that we can use it to
5907+
// perform qualified lookup, and to get the correct visibility for
5908+
// @testable imports.
59075909
DeclContext *DCForModules = &SF;
59085910
Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
59095911
DCForModules);
@@ -5935,19 +5937,17 @@ void DotExprLookup::performLookup(ide::CodeCompletionContext &CompletionCtx,
59355937

59365938
for (auto &Solution: Solutions) {
59375939
Lookup.setIsStaticMetatype(Solution.BaseIsStaticMetaType);
5938-
Lookup.getPostfixKeywordCompletions(Solution.Ty, BaseExpr);
5940+
Lookup.getPostfixKeywordCompletions(Solution.BaseTy, BaseExpr);
59395941
Lookup.setExpectedTypes(Solution.ExpectedTypes,
5940-
Solution.IsSingleExpressionClosure,
5942+
Solution.IsSingleExpressionBody,
59415943
Solution.ExpectsNonVoid);
5942-
if (isDynamicLookup(Solution.Ty))
5944+
if (isDynamicLookup(Solution.BaseTy))
59435945
Lookup.setIsDynamicLookup();
5944-
Lookup.getValueExprCompletions(Solution.Ty, Solution.ReferencedDecl);
5946+
Lookup.getValueExprCompletions(Solution.BaseTy, Solution.BaseDecl);
59455947
}
59465948

59475949
SourceFile *SF = DC->getParentSourceFile();
5948-
// FIXME: There may be multiple of these now.
5949-
CompletionCtx.typeContextKind = Lookup.typeContextKind();
5950-
processModuleRequests(CompletionCtx, Lookup, *SF, Consumer);
5950+
deliverCompletionResults(CompletionCtx, Lookup, *SF, Consumer);
59515951
}
59525952

59535953
bool CodeCompletionCallbacksImpl::trySolverCompletion() {
@@ -5985,7 +5985,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion() {
59855985
CompletionCollector(Context.CompletionCallback, &Lookup);
59865986
typeCheckContextAt(CurDeclContext, CompletionLoc);
59875987

5988-
// This (should) only happens in cases where the expression isn't
5988+
// This (hopefully) only happens in cases where the expression isn't
59895989
// typechecked during normal compilation either (e.g. member completion in a
59905990
// switch case where there switched value is invalid). Having normal
59915991
// typechecking still resolve even these cases would be beneficial for
@@ -6529,112 +6529,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
65296529
break;
65306530
}
65316531

6532-
llvm::SmallPtrSet<Identifier, 8> seenModuleNames;
6533-
6534-
for (auto &Request: Lookup.RequestedCachedResults) {
6535-
// Use the current SourceFile as the DeclContext so that we can use it to
6536-
// perform qualified lookup, and to get the correct visibility for
6537-
// @testable imports.
6538-
const SourceFile &SF = P.SF;
6539-
6540-
llvm::DenseSet<CodeCompletionCache::Key> ImportsSeen;
6541-
auto handleImport = [&](ModuleDecl::ImportedModule Import) {
6542-
ModuleDecl *TheModule = Import.importedModule;
6543-
ModuleDecl::AccessPathTy Path = Import.accessPath;
6544-
if (TheModule->getFiles().empty())
6545-
return;
6546-
6547-
// Clang submodules are ignored and there's no lookup cost involved,
6548-
// so just ignore them and don't put the empty results in the cache
6549-
// because putting a lot of objects in the cache will push out
6550-
// other lookups.
6551-
if (isClangSubModule(TheModule))
6552-
return;
6553-
6554-
std::vector<std::string> AccessPath;
6555-
for (auto Piece : Path) {
6556-
AccessPath.push_back(std::string(Piece.Item));
6557-
}
6558-
6559-
StringRef ModuleFilename = TheModule->getModuleFilename();
6560-
// ModuleFilename can be empty if something strange happened during
6561-
// module loading, for example, the module file is corrupted.
6562-
if (!ModuleFilename.empty()) {
6563-
auto &Ctx = TheModule->getASTContext();
6564-
CodeCompletionCache::Key K{
6565-
ModuleFilename.str(),
6566-
std::string(TheModule->getName()),
6567-
AccessPath,
6568-
Request.NeedLeadingDot,
6569-
SF.hasTestableOrPrivateImport(
6570-
AccessLevel::Internal, TheModule,
6571-
SourceFile::ImportQueryKind::TestableOnly),
6572-
SF.hasTestableOrPrivateImport(
6573-
AccessLevel::Internal, TheModule,
6574-
SourceFile::ImportQueryKind::PrivateOnly),
6575-
Ctx.LangOpts.CodeCompleteInitsInPostfixExpr,
6576-
CompletionContext.getAnnotateResult(),
6577-
};
6578-
6579-
using PairType = llvm::DenseSet<swift::ide::CodeCompletionCache::Key,
6580-
llvm::DenseMapInfo<CodeCompletionCache::Key>>::iterator;
6581-
std::pair<PairType, bool> Result = ImportsSeen.insert(K);
6582-
if (!Result.second)
6583-
return; // already handled.
6584-
RequestedModules.push_back({std::move(K), TheModule,
6585-
Request.OnlyTypes, Request.OnlyPrecedenceGroups});
6586-
6587-
if (Request.IncludeModuleQualifier &&
6588-
seenModuleNames.insert(TheModule->getName()).second)
6589-
Lookup.addModuleName(TheModule);
6590-
}
6591-
};
6592-
6593-
if (Request.TheModule) {
6594-
// FIXME: actually check imports.
6595-
for (auto Import : namelookup::getAllImports(Request.TheModule)) {
6596-
handleImport(Import);
6597-
}
6598-
} else {
6599-
// Add results from current module.
6600-
Lookup.getToplevelCompletions(Request.OnlyTypes);
6601-
6602-
// Add the qualifying module name
6603-
auto curModule = CurDeclContext->getParentModule();
6604-
if (Request.IncludeModuleQualifier &&
6605-
seenModuleNames.insert(curModule->getName()).second)
6606-
Lookup.addModuleName(curModule);
6607-
6608-
// Add results for all imported modules.
6609-
SmallVector<ModuleDecl::ImportedModule, 4> Imports;
6610-
auto *SF = CurDeclContext->getParentSourceFile();
6611-
SF->getImportedModules(
6612-
Imports, {ModuleDecl::ImportFilterKind::Public,
6613-
ModuleDecl::ImportFilterKind::Private,
6614-
ModuleDecl::ImportFilterKind::ImplementationOnly});
6615-
6616-
for (auto Imported : Imports) {
6617-
for (auto Import : namelookup::getAllImports(Imported.importedModule))
6618-
handleImport(Import);
6619-
}
6620-
}
6621-
}
6622-
Lookup.RequestedCachedResults.clear();
6623-
6624-
CompletionContext.typeContextKind = Lookup.typeContextKind();
6625-
6626-
deliverCompletionResults();
6627-
}
6628-
6629-
void CodeCompletionCallbacksImpl::deliverCompletionResults() {
6630-
// Use the current SourceFile as the DeclContext so that we can use it to
6631-
// perform qualified lookup, and to get the correct visibility for
6632-
// @testable imports.
6633-
DeclContext *DCForModules = &P.SF;
6634-
6635-
Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
6636-
DCForModules);
6637-
RequestedModules.clear();
6532+
deliverCompletionResults(CompletionContext, Lookup, P.SF, Consumer);
66386533
}
66396534

66406535
void PrintingCodeCompletionConsumer::handleResults(

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
using namespace swift;
3939
using namespace ide;
4040

41-
4241
//===----------------------------------------------------------------------===//
4342
// typeCheckContextAt(DeclContext, SourceLoc)
4443
//===----------------------------------------------------------------------===//

lib/Parse/ParseExpr.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2879,7 +2879,6 @@ ParserResult<Expr> Parser::parseExprClosure() {
28792879
// may be incomplete and the type mismatch in return statement will just
28802880
// confuse the type checker.
28812881
bool hasSingleExpressionBody = false;
2882-
// FIXME: make this change separately
28832882
if (!missingRBrace && bodyElements.size() == 1 &&
28842883
(!Status.hasCodeCompletion() || isMemberCompletion(bodyElements[0]))) {
28852884
// If the closure's only body element is a single return statement,

lib/Sema/TypeCheckCodeCompletion.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,31 +1007,31 @@ void DotExprLookup::sawSolution(const constraints::Solution &S) {
10071007
ReferencedDecl = SelectedOverload->choice.getDeclOrNull();
10081008

10091009
auto Key = std::make_pair(BaseTy, ReferencedDecl);
1010-
auto Ret = ResultToIndex.insert({Key, Solutions.size()});
1010+
auto Ret = BaseToSolutionIdx.insert({Key, Solutions.size()});
10111011
if (!Ret.second && ExpectedTy) {
10121012
Solutions[Ret.first->getSecond()].ExpectedTypes.push_back(ExpectedTy);
10131013
} else {
10141014
bool ISDMT = S.isStaticallyDerivedMetatype(ParsedExpr);
1015-
bool ISEC = false;
1015+
bool SingleExprBody = false;
10161016
bool DisallowVoid = ExpectedTy
10171017
? !ExpectedTy->isVoid()
10181018
: !ParentExpr && CS.getContextualTypePurpose(
10191019
CompletionExpr) != CTP_Unused;
10201020

10211021
if (!ParentExpr) {
10221022
if (CS.getContextualTypePurpose(CompletionExpr) == CTP_ReturnSingleExpr)
1023-
ISEC = true;
1023+
SingleExprBody = true;
10241024
} else if (auto *ParentCE = dyn_cast<ClosureExpr>(ParentExpr)) {
10251025
if (ParentCE->hasSingleExpressionBody() &&
10261026
ParentCE->getSingleExpressionBody() == CompletionExpr) {
10271027
ASTNode Last = ParentCE->getBody()->getLastElement();
10281028
if (!Last.isStmt(StmtKind::Return) || Last.isImplicit())
1029-
ISEC = true;
1029+
SingleExprBody = true;
10301030
}
10311031
}
10321032

10331033
Solutions.push_back(
1034-
{BaseTy, ReferencedDecl, {}, DisallowVoid, ISDMT, ISEC});
1034+
{BaseTy, ReferencedDecl, {}, DisallowVoid, ISDMT, SingleExprBody});
10351035
if (ExpectedTy)
10361036
Solutions.back().ExpectedTypes.push_back(ExpectedTy);
10371037
}

0 commit comments

Comments
 (0)