-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
Copy pathExprCompletion.cpp
124 lines (107 loc) · 4.49 KB
/
ExprCompletion.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//===--- ExprCompletion.cpp -----------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/IDE/ExprCompletion.h"
#include "swift/IDE/CodeCompletion.h"
#include "swift/IDE/CompletionLookup.h"
#include "swift/Sema/ConstraintSystem.h"
using namespace swift;
using namespace swift::ide;
using namespace swift::constraints;
static bool solutionSpecificVarTypesEqual(
const llvm::SmallDenseMap<const VarDecl *, Type> &LHS,
const llvm::SmallDenseMap<const VarDecl *, Type> &RHS) {
if (LHS.size() != RHS.size()) {
return false;
}
for (auto LHSEntry : LHS) {
auto RHSEntry = RHS.find(LHSEntry.first);
if (RHSEntry == RHS.end()) {
// Entry of the LHS doesn't exist in RHS
return false;
} else if (!nullableTypesEqual(LHSEntry.second, RHSEntry->second)) {
return false;
}
}
return true;
}
bool ExprTypeCheckCompletionCallback::Result::operator==(
const Result &Other) const {
return IsImpliedResult == Other.IsImpliedResult &&
IsInAsyncContext == Other.IsInAsyncContext &&
nullableTypesEqual(UnresolvedMemberBaseType,
Other.UnresolvedMemberBaseType) &&
solutionSpecificVarTypesEqual(SolutionSpecificVarTypes,
Other.SolutionSpecificVarTypes);
}
void ExprTypeCheckCompletionCallback::addExpectedType(Type ExpectedType) {
auto IsEqual = [&ExpectedType](Type Other) {
return nullableTypesEqual(ExpectedType, Other);
};
if (llvm::any_of(ExpectedTypes, IsEqual)) {
return;
}
ExpectedTypes.push_back(ExpectedType);
}
void ExprTypeCheckCompletionCallback::addResult(
bool IsImpliedResult, bool IsInAsyncContext, Type UnresolvedMemberBaseType,
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes) {
if (!AddUnresolvedMemberCompletions) {
UnresolvedMemberBaseType = Type();
}
Result NewResult = {IsImpliedResult, IsInAsyncContext,
UnresolvedMemberBaseType, SolutionSpecificVarTypes};
if (llvm::is_contained(Results, NewResult)) {
return;
}
Results.push_back(NewResult);
}
void ExprTypeCheckCompletionCallback::sawSolutionImpl(
const constraints::Solution &S) {
Type ExpectedTy = getTypeForCompletion(S, CompletionExpr);
bool IsImpliedResult = isImpliedResult(S, CompletionExpr);
bool IsAsync = isContextAsync(S, DC);
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes;
getSolutionSpecificVarTypes(S, SolutionSpecificVarTypes);
addResult(IsImpliedResult, IsAsync, ExpectedTy, SolutionSpecificVarTypes);
addExpectedType(ExpectedTy);
if (auto PatternMatchType = getPatternMatchType(S, CompletionExpr)) {
addResult(IsImpliedResult, IsAsync, PatternMatchType,
SolutionSpecificVarTypes);
addExpectedType(PatternMatchType);
}
}
void ExprTypeCheckCompletionCallback::collectResults(
SourceLoc CCLoc, ide::CodeCompletionContext &CompletionCtx) {
ASTContext &Ctx = DC->getASTContext();
CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
&CompletionCtx);
Lookup.shouldCheckForDuplicates(Results.size() > 1);
// The type context that is being used for global results.
ExpectedTypeContext UnifiedTypeContext;
UnifiedTypeContext.setPreferNonVoid(true);
bool UnifiedCanHandleAsync = false;
for (auto &Result : Results) {
WithSolutionSpecificVarTypesRAII VarTypes(Result.SolutionSpecificVarTypes);
Lookup.setExpectedTypes(ExpectedTypes, Result.IsImpliedResult);
Lookup.setCanCurrDeclContextHandleAsync(Result.IsInAsyncContext);
Lookup.setSolutionSpecificVarTypes(Result.SolutionSpecificVarTypes);
Lookup.getValueCompletionsInDeclContext(CCLoc);
Lookup.getSelfTypeCompletionInDeclContext(CCLoc, /*isForDeclResult=*/false);
if (Result.UnresolvedMemberBaseType) {
Lookup.getUnresolvedMemberCompletions(Result.UnresolvedMemberBaseType);
}
UnifiedTypeContext.merge(*Lookup.getExpectedTypeContext());
UnifiedCanHandleAsync |= Result.IsInAsyncContext;
}
collectCompletionResults(CompletionCtx, Lookup, DC, UnifiedTypeContext,
UnifiedCanHandleAsync);
}