Skip to content

Commit 471b24f

Browse files
committed
[CodeCompletion] Move solver-based DotExpr completion to its own file
1 parent d190e3f commit 471b24f

9 files changed

+255
-168
lines changed

include/swift/IDE/CodeCompletion.h

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/IDE/CodeCompletionContext.h"
1818
#include "swift/IDE/CodeCompletionResult.h"
1919
#include "swift/IDE/CodeCompletionResultSink.h"
20+
#include "swift/IDE/CompletionLookup.h"
2021

2122
namespace swift {
2223
class CodeCompletionCallbacksFactory;
@@ -58,10 +59,15 @@ ArrayRef<T> copyArray(llvm::BumpPtrAllocator &Allocator,
5859
return llvm::makeArrayRef(Buffer, Arr.size());
5960
}
6061

62+
bool isDynamicLookup(Type T);
63+
6164
void postProcessResults(MutableArrayRef<CodeCompletionResult *> results,
6265
CompletionKind Kind, DeclContext *DC,
6366
CodeCompletionResultSink *Sink);
6467

68+
void deliverCompletionResults(CodeCompletionContext &CompletionContext,
69+
CompletionLookup &Lookup, DeclContext *DC,
70+
CodeCompletionConsumer &Consumer);
6571

6672
/// Create a factory for code completion callbacks.
6773
CodeCompletionCallbacksFactory *

include/swift/IDE/DotExprCompletion.h

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//===--- DotExprCodeCompletion.h ------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 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_DOTEXPRCODECOMPLETION_H
14+
#define SWIFT_IDE_DOTEXPRCODECOMPLETION_H
15+
16+
#include "swift/IDE/CodeCompletionConsumer.h"
17+
#include "swift/IDE/CodeCompletionContext.h"
18+
#include "swift/Sema/CodeCompletionTypeChecking.h"
19+
20+
namespace swift {
21+
namespace ide {
22+
23+
/// Used to collect and store information needed to perform member completion
24+
/// (\c CompletionKind::DotExpr ) from the solutions formed during expression
25+
/// type-checking.
26+
class DotExprTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
27+
public:
28+
struct Result {
29+
Type BaseTy;
30+
ValueDecl *BaseDecl;
31+
SmallVector<Type, 4> ExpectedTypes;
32+
bool ExpectsNonVoid;
33+
bool BaseIsStaticMetaType;
34+
bool IsImplicitSingleExpressionReturn;
35+
};
36+
37+
private:
38+
DeclContext *DC;
39+
CodeCompletionExpr *CompletionExpr;
40+
SmallVector<Result, 4> Results;
41+
llvm::DenseMap<std::pair<Type, Decl *>, size_t> BaseToSolutionIdx;
42+
bool GotCallback = false;
43+
44+
public:
45+
DotExprTypeCheckCompletionCallback(DeclContext *DC,
46+
CodeCompletionExpr *CompletionExpr)
47+
: DC(DC), CompletionExpr(CompletionExpr) {}
48+
49+
/// Get the results collected from any sawSolutions() callbacks recevied so
50+
/// far.
51+
ArrayRef<Result> getResults() const { return Results; }
52+
53+
/// True if at least one solution was passed via the \c sawSolution
54+
/// callback.
55+
bool gotCallback() const { return GotCallback; }
56+
57+
/// Typecheck the code completion expression in isolation, calling
58+
/// \c sawSolution for each solution formed.
59+
void fallbackTypeCheck();
60+
61+
void sawSolution(const constraints::Solution &solution) override;
62+
};
63+
64+
void deliverDotExprResults(
65+
ArrayRef<DotExprTypeCheckCompletionCallback::Result> Results,
66+
Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc, bool IsInSelector,
67+
CodeCompletionContext &CompletionCtx, CodeCompletionConsumer &Consumer);
68+
69+
} // end namespace ide
70+
} // end namespace swift
71+
72+
#endif // SWIFT_IDE_DOTEXPRCODECOMPLETION_H

include/swift/Sema/CodeCompletionTypeChecking.h

-41
Original file line numberDiff line numberDiff line change
@@ -44,47 +44,6 @@ namespace swift {
4444
};
4545

4646

47-
/// Used to collect and store information needed to perform member completion
48-
/// (\c CompletionKind::DotExpr ) from the solutions formed during expression
49-
/// type-checking.
50-
class DotExprTypeCheckCompletionCallback: public TypeCheckCompletionCallback {
51-
public:
52-
struct Result {
53-
Type BaseTy;
54-
ValueDecl* BaseDecl;
55-
SmallVector<Type, 4> ExpectedTypes;
56-
bool ExpectsNonVoid;
57-
bool BaseIsStaticMetaType;
58-
bool IsImplicitSingleExpressionReturn;
59-
};
60-
61-
private:
62-
DeclContext *DC;
63-
CodeCompletionExpr *CompletionExpr;
64-
SmallVector<Result, 4> Results;
65-
llvm::DenseMap<std::pair<Type, Decl*>, size_t> BaseToSolutionIdx;
66-
bool GotCallback = false;
67-
68-
public:
69-
DotExprTypeCheckCompletionCallback(DeclContext *DC,
70-
CodeCompletionExpr *CompletionExpr)
71-
: DC(DC), CompletionExpr(CompletionExpr) {}
72-
73-
/// Get the results collected from any sawSolutions() callbacks recevied so
74-
/// far.
75-
ArrayRef<Result> getResults() const { return Results; }
76-
77-
/// True if at least one solution was passed via the \c sawSolution
78-
/// callback.
79-
bool gotCallback() const { return GotCallback; }
80-
81-
/// Typecheck the code completion expression in isolation, calling
82-
/// \c sawSolution for each solution formed.
83-
void fallbackTypeCheck();
84-
85-
void sawSolution(const constraints::Solution &solution) override;
86-
};
87-
8847
/// Used to collect and store information needed to perform unresolved member
8948
/// completion (\c CompletionKind::UnresolvedMember ) from the solutions
9049
/// formed during expression type-checking.

include/swift/Sema/IDETypeChecking.h

+31
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "swift/AST/Identifier.h"
2323
#include "swift/Basic/SourceLoc.h"
24+
#include "swift/Sema/ConstraintSystem.h"
2425
#include <memory>
2526
#include <tuple>
2627

@@ -137,6 +138,36 @@ namespace swift {
137138
/// Type check a function body element which is at \p TagetLoc .
138139
bool typeCheckASTNodeAtLoc(DeclContext *DC, SourceLoc TargetLoc);
139140

141+
/// Thunk around \c TypeChecker::typeCheckForCodeCompletion to make it
142+
/// available to \c swift::ide.
143+
/// Type check the given expression and provide results back to code
144+
/// completion via specified callback.
145+
///
146+
/// This method is designed to be used for code completion which means that
147+
/// it doesn't mutate given expression, even if there is a single valid
148+
/// solution, and constraint solver is allowed to produce partially correct
149+
/// solutions. Such solutions can have any number of holes in them.
150+
///
151+
/// \returns `true` if target was applicable and it was possible to infer
152+
/// types for code completion, `false` othrewise.
153+
bool typeCheckForCodeCompletion(
154+
constraints::SolutionApplicationTarget &target, bool needsPrecheck,
155+
llvm::function_ref<void(const constraints::Solution &)> callback);
156+
157+
Type getTypeForCompletion(const constraints::Solution &S, Expr *E);
158+
159+
/// Whether the given completion expression is the only expression in its
160+
/// containing closure or function body and its value is implicitly returned.
161+
///
162+
/// If these conditions are met, code completion needs to avoid penalizing
163+
/// completion results that don't match the expected return type when
164+
/// computing type relations, as since no return statement was explicitly
165+
/// written by the user, it's possible they intend the single expression not
166+
/// as the return value but merely the first entry in a multi-statement body
167+
/// they just haven't finished writing yet.
168+
bool isImplicitSingleExpressionReturn(constraints::ConstraintSystem &CS,
169+
Expr *CompletionExpr);
170+
140171
LookupResult
141172
lookupSemanticMember(DeclContext *DC, Type ty, DeclName name);
142173

lib/IDE/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ add_swift_host_library(swiftIDE STATIC
1818
CompletionOverrideLookup.cpp
1919
ConformingMethodList.cpp
2020
DependencyChecking.cpp
21+
DotExprCompletion.cpp
2122
ExprContextAnalysis.cpp
2223
Formatting.cpp
2324
FuzzyStringMatcher.cpp

lib/IDE/CodeCompletion.cpp

+5-45
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "swift/IDE/CodeCompletionStringPrinter.h"
3939
#include "swift/IDE/CompletionLookup.h"
4040
#include "swift/IDE/CompletionOverrideLookup.h"
41+
#include "swift/IDE/DotExprCompletion.h"
4142
#include "swift/IDE/Utils.h"
4243
#include "swift/Parse/CodeCompletionCallbacks.h"
4344
#include "swift/Sema/CodeCompletionTypeChecking.h"
@@ -653,7 +654,7 @@ void CodeCompletionCallbacksImpl::completeTypeAttrBeginning() {
653654
Kind = CompletionKind::TypeAttrBeginning;
654655
}
655656

656-
static bool isDynamicLookup(Type T) {
657+
bool swift::ide::isDynamicLookup(Type T) {
657658
return T->getRValueType()->isAnyObject();
658659
}
659660

@@ -1198,10 +1199,9 @@ void swift::ide::postProcessResults(
11981199
}
11991200
}
12001201

1201-
static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
1202-
CompletionLookup &Lookup,
1203-
DeclContext *DC,
1204-
CodeCompletionConsumer &Consumer) {
1202+
void swift::ide::deliverCompletionResults(
1203+
CodeCompletionContext &CompletionContext, CompletionLookup &Lookup,
1204+
DeclContext *DC, CodeCompletionConsumer &Consumer) {
12051205
auto &SF = *DC->getParentSourceFile();
12061206
llvm::SmallPtrSet<Identifier, 8> seenModuleNames;
12071207
std::vector<RequestedCachedModule> RequestedModules;
@@ -1396,46 +1396,6 @@ void deliverKeyPathResults(
13961396
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
13971397
}
13981398

1399-
void deliverDotExprResults(
1400-
ArrayRef<DotExprTypeCheckCompletionCallback::Result> Results,
1401-
Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc, bool IsInSelector,
1402-
ide::CodeCompletionContext &CompletionCtx,
1403-
CodeCompletionConsumer &Consumer) {
1404-
ASTContext &Ctx = DC->getASTContext();
1405-
CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
1406-
&CompletionCtx);
1407-
1408-
if (DotLoc.isValid())
1409-
Lookup.setHaveDot(DotLoc);
1410-
1411-
Lookup.setIsSuperRefExpr(isa<SuperRefExpr>(BaseExpr));
1412-
1413-
if (auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
1414-
Lookup.setIsSelfRefExpr(DRE->getDecl()->getName() == Ctx.Id_self);
1415-
1416-
if (isa<BindOptionalExpr>(BaseExpr) || isa<ForceValueExpr>(BaseExpr))
1417-
Lookup.setIsUnwrappedOptional(true);
1418-
1419-
if (IsInSelector) {
1420-
Lookup.includeInstanceMembers();
1421-
Lookup.setPreferFunctionReferencesToCalls();
1422-
}
1423-
1424-
Lookup.shouldCheckForDuplicates(Results.size() > 1);
1425-
for (auto &Result: Results) {
1426-
Lookup.setIsStaticMetatype(Result.BaseIsStaticMetaType);
1427-
Lookup.getPostfixKeywordCompletions(Result.BaseTy, BaseExpr);
1428-
Lookup.setExpectedTypes(Result.ExpectedTypes,
1429-
Result.IsImplicitSingleExpressionReturn,
1430-
Result.ExpectsNonVoid);
1431-
if (isDynamicLookup(Result.BaseTy))
1432-
Lookup.setIsDynamicLookup();
1433-
Lookup.getValueExprCompletions(Result.BaseTy, Result.BaseDecl);
1434-
}
1435-
1436-
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
1437-
}
1438-
14391399
bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
14401400
assert(ParsedExpr || CurDeclContext);
14411401

0 commit comments

Comments
 (0)