@@ -40,8 +40,9 @@ void TypeCheckCompletionCallback::fallbackTypeCheck(DeclContext *DC) {
4040
4141// MARK: - Utility functions for subclasses of TypeCheckCompletionCallback
4242
43- Type swift::ide::getTypeForCompletion (const constraints::Solution &S, Expr *E) {
44- if (!S.hasType (E)) {
43+ Type swift::ide::getTypeForCompletion (const constraints::Solution &S,
44+ ASTNode Node) {
45+ if (!S.hasType (Node)) {
4546 assert (false && " Expression wasn't type checked?" );
4647 return nullptr ;
4748 }
@@ -66,8 +67,8 @@ Type swift::ide::getTypeForCompletion(const constraints::Solution &S, Expr *E) {
6667 // expression should still have a type of `[T]` instead of `[<<hole>>]`
6768 // because it helps to produce correct contextual member list based on
6869 // a conformance requirement associated with generic parameter `T`.
69- if (isa <CodeCompletionExpr>(E )) {
70- auto completionTy = S.getType (E ).transform ([&](Type type) -> Type {
70+ if (isExpr <CodeCompletionExpr>(Node )) {
71+ auto completionTy = S.getType (Node ).transform ([&](Type type) -> Type {
7172 if (auto *typeVar = type->getAs <TypeVariableType>())
7273 return S.getFixedType (typeVar);
7374 return type;
@@ -92,18 +93,77 @@ Type swift::ide::getTypeForCompletion(const constraints::Solution &S, Expr *E) {
9293 return type;
9394 }));
9495 } else {
95- Result = S.getResolvedType (E );
96+ Result = S.getResolvedType (Node );
9697 }
9798
9899 if (!Result || Result->is <UnresolvedType>()) {
99- Result = CS.getContextualType (E , /* forConstraint=*/ false );
100+ Result = CS.getContextualType (Node , /* forConstraint=*/ false );
100101 }
101102 if (Result && Result->is <UnresolvedType>()) {
102103 Result = Type ();
103104 }
104105 return Result;
105106}
106107
108+ // / If the code completion expression \p E occurs in a pattern matching
109+ // / position, we have an AST that looks like this.
110+ // / \code
111+ // / (binary_expr implicit type='$T3'
112+ // / (overloaded_decl_ref_expr function_ref=compound decls=[
113+ // / Swift.(file).~=,
114+ // / Swift.(file).Optional extension.~=])
115+ // / (argument_list implicit
116+ // / (argument
117+ // / (code_completion_expr implicit type='$T1'))
118+ // / (argument
119+ // / (declref_expr implicit decl=swift_ide_test.(file).foo(x:).$match))))
120+ // / \endcode
121+ // / If the code completion expression occurs in such an AST, return the
122+ // / declaration of the \c $match variable, otherwise return \c nullptr.
123+ static VarDecl *getMatchVarIfInPatternMatch (Expr *E, ConstraintSystem &CS) {
124+ auto &Context = CS.getASTContext ();
125+
126+ auto *Binary = dyn_cast_or_null<BinaryExpr>(CS.getParentExpr (E));
127+ if (!Binary || !Binary->isImplicit () || Binary->getLHS () != E) {
128+ return nullptr ;
129+ }
130+
131+ auto CalledOperator = Binary->getFn ();
132+ if (!isPatternMatchingOperator (CalledOperator)) {
133+ return nullptr ;
134+ }
135+
136+ auto MatchArg = dyn_cast_or_null<DeclRefExpr>(Binary->getRHS ());
137+ if (!MatchArg || !MatchArg->isImplicit ()) {
138+ return nullptr ;
139+ }
140+
141+ auto MatchVar = MatchArg->getDecl ();
142+ if (MatchVar && MatchVar->isImplicit () &&
143+ MatchVar->getBaseName () == Context.Id_PatternMatchVar ) {
144+ return dyn_cast<VarDecl>(MatchVar);
145+ } else {
146+ return nullptr ;
147+ }
148+ }
149+
150+ Type swift::ide::getPatternMatchType (const constraints::Solution &S, Expr *E) {
151+ if (auto MatchVar = getMatchVarIfInPatternMatch (E, S.getConstraintSystem ())) {
152+ Type MatchVarType;
153+ // If the MatchVar has an explicit type, it's not part of the solution. But
154+ // we can look it up in the constraint system directly.
155+ if (auto T = S.getConstraintSystem ().getVarType (MatchVar)) {
156+ MatchVarType = T;
157+ } else {
158+ MatchVarType = getTypeForCompletion (S, MatchVar);
159+ }
160+ if (MatchVarType) {
161+ return MatchVarType;
162+ }
163+ }
164+ return nullptr ;
165+ }
166+
107167bool swift::ide::isImplicitSingleExpressionReturn (ConstraintSystem &CS,
108168 Expr *CompletionExpr) {
109169 Expr *ParentExpr = CS.getParentExpr (CompletionExpr);
@@ -148,3 +208,14 @@ bool swift::ide::isContextAsync(const constraints::Solution &S,
148208 // async.
149209 return canDeclContextHandleAsync (DC);
150210}
211+
212+ bool swift::ide::nullableTypesEqual (Type LHS, Type RHS) {
213+ if (LHS.isNull () && RHS.isNull ()) {
214+ return true ;
215+ } else if (LHS.isNull () || RHS.isNull ()) {
216+ // One type is null but the other is not.
217+ return false ;
218+ } else {
219+ return LHS->isEqual (RHS);
220+ }
221+ }
0 commit comments