Skip to content

Commit 67c097a

Browse files
authored
Merge pull request #41948 from ahoppen/pr/migrate-afterpoundexpr-solver-based
[CodeCompletion] Migrate AfterPoundExprCompletion to solver-based
2 parents d58bd27 + 2a96221 commit 67c097a

File tree

4 files changed

+138
-11
lines changed

4 files changed

+138
-11
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//===--- AfterPoundExprCompletion.h ---------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_IDE_AFTERPOUNDEXPRCOMPLETION_H
14+
#define SWIFT_IDE_AFTERPOUNDEXPRCOMPLETION_H
15+
16+
#include "swift/IDE/CodeCompletionConsumer.h"
17+
#include "swift/IDE/CodeCompletionContext.h"
18+
#include "swift/IDE/TypeCheckCompletionCallback.h"
19+
20+
namespace swift {
21+
namespace ide {
22+
23+
/// Used to collect and store information needed to perform unresolved member
24+
/// completion (\c CompletionKind::UnresolvedMember ) from the solutions
25+
/// formed during expression type-checking.
26+
class AfterPoundExprCompletion : public TypeCheckCompletionCallback {
27+
struct Result {
28+
Type ExpectedTy;
29+
bool IsImplicitSingleExpressionReturn;
30+
31+
/// Whether the surrounding context is async and thus calling async
32+
/// functions is supported.
33+
bool IsInAsyncContext;
34+
};
35+
36+
CodeCompletionExpr *CompletionExpr;
37+
DeclContext *DC;
38+
Optional<StmtKind> ParentStmtKind;
39+
40+
SmallVector<Result, 4> Results;
41+
42+
void sawSolutionImpl(const constraints::Solution &solution) override;
43+
44+
public:
45+
AfterPoundExprCompletion(CodeCompletionExpr *CompletionExpr, DeclContext *DC,
46+
Optional<StmtKind> ParentStmtKind)
47+
: CompletionExpr(CompletionExpr), DC(DC), ParentStmtKind(ParentStmtKind) {
48+
}
49+
50+
void deliverResults(ide::CodeCompletionContext &CompletionCtx,
51+
CodeCompletionConsumer &Consumer);
52+
};
53+
54+
} // end namespace ide
55+
} // end namespace swift
56+
57+
#endif // SWIFT_IDE_AFTERPOUNDEXPRCOMPLETION_H

lib/IDE/AfterPoundExprCompletion.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//===--- AfterPoundExprCompletion.cpp -------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/IDE/AfterPoundExprCompletion.h"
14+
#include "swift/IDE/CodeCompletion.h"
15+
#include "swift/IDE/CompletionLookup.h"
16+
#include "swift/Sema/CompletionContextFinder.h"
17+
#include "swift/Sema/ConstraintSystem.h"
18+
#include "swift/Sema/IDETypeChecking.h"
19+
20+
using namespace swift;
21+
using namespace swift::constraints;
22+
using namespace swift::ide;
23+
24+
void AfterPoundExprCompletion::sawSolutionImpl(const constraints::Solution &S) {
25+
auto &CS = S.getConstraintSystem();
26+
Type ExpectedTy = getTypeForCompletion(S, CompletionExpr);
27+
28+
bool IsAsync = isContextAsync(S, DC);
29+
30+
// If ExpectedTy is a duplicate of any other result, ignore this solution.
31+
auto IsEqual = [&](const Result &R) {
32+
return R.ExpectedTy->isEqual(ExpectedTy);
33+
};
34+
if (!llvm::any_of(Results, IsEqual)) {
35+
bool SingleExprBody = isImplicitSingleExpressionReturn(CS, CompletionExpr);
36+
Results.push_back({ExpectedTy, SingleExprBody, IsAsync});
37+
}
38+
}
39+
40+
void AfterPoundExprCompletion::deliverResults(
41+
ide::CodeCompletionContext &CompletionCtx,
42+
CodeCompletionConsumer &Consumer) {
43+
ASTContext &Ctx = DC->getASTContext();
44+
CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
45+
&CompletionCtx);
46+
47+
Lookup.shouldCheckForDuplicates(Results.size() > 1);
48+
49+
for (auto &Result : Results) {
50+
Lookup.setExpectedTypes({Result.ExpectedTy},
51+
Result.IsImplicitSingleExpressionReturn,
52+
/*expectsNonVoid=*/true);
53+
Lookup.addPoundAvailable(ParentStmtKind);
54+
Lookup.addPoundLiteralCompletions(/*needPound=*/false);
55+
Lookup.addObjCPoundKeywordCompletions(/*needPound=*/false);
56+
}
57+
58+
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
59+
}

lib/IDE/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
add_swift_host_library(swiftIDE STATIC
3+
AfterPoundExprCompletion.cpp
34
ArgumentCompletion.cpp
45
CodeCompletion.cpp
56
CodeCompletionCache.cpp

lib/IDE/CodeCompletion.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "swift/ClangImporter/ClangImporter.h"
3333
#include "swift/ClangImporter/ClangModule.h"
3434
#include "swift/Frontend/FrontendOptions.h"
35+
#include "swift/IDE/AfterPoundExprCompletion.h"
3536
#include "swift/IDE/ArgumentCompletion.h"
3637
#include "swift/IDE/CodeCompletionCache.h"
3738
#include "swift/IDE/CodeCompletionConsumer.h"
@@ -1418,6 +1419,25 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
14181419
Lookup.deliverResults(CCLoc, CompletionContext, Consumer);
14191420
return true;
14201421
}
1422+
case CompletionKind::AfterPoundExpr: {
1423+
assert(CodeCompleteTokenExpr);
1424+
assert(CurDeclContext);
1425+
1426+
AfterPoundExprCompletion Lookup(CodeCompleteTokenExpr, CurDeclContext,
1427+
ParentStmtKind);
1428+
llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector(
1429+
Context.CompletionCallback, &Lookup);
1430+
typeCheckContextAt(CurDeclContext, CompletionLoc);
1431+
1432+
if (!Lookup.gotCallback()) {
1433+
Lookup.fallbackTypeCheck(CurDeclContext);
1434+
}
1435+
1436+
addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
1437+
1438+
Lookup.deliverResults(CompletionContext, Consumer);
1439+
return true;
1440+
}
14211441
default:
14221442
return false;
14231443
}
@@ -1543,6 +1563,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
15431563
case CompletionKind::StmtOrExpr:
15441564
case CompletionKind::ForEachSequence:
15451565
case CompletionKind::PostfixExprBeginning:
1566+
case CompletionKind::AfterPoundExpr:
15461567
llvm_unreachable("should be already handled");
15471568
return;
15481569

@@ -1829,17 +1850,6 @@ void CodeCompletionCallbacksImpl::doneParsing() {
18291850
break;
18301851
}
18311852

1832-
case CompletionKind::AfterPoundExpr: {
1833-
ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
1834-
Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
1835-
ContextInfo.isImplicitSingleExpressionReturn());
1836-
1837-
Lookup.addPoundAvailable(ParentStmtKind);
1838-
Lookup.addPoundLiteralCompletions(/*needPound=*/false);
1839-
Lookup.addObjCPoundKeywordCompletions(/*needPound=*/false);
1840-
break;
1841-
}
1842-
18431853
case CompletionKind::AfterPoundDirective: {
18441854
addPoundDirectives(CompletionContext.getResultSink());
18451855
// FIXME: Add pound expressions (e.g. '#selector()') if it's at statements

0 commit comments

Comments
 (0)