16
16
#include " swift/AST/GenericEnvironment.h"
17
17
#include " swift/AST/NameLookup.h"
18
18
#include " swift/AST/USRGeneration.h"
19
+ #include " swift/IDE/SelectedOverloadInfo.h"
19
20
#include " swift/IDE/TypeCheckCompletionCallback.h"
20
21
#include " swift/Parse/IDEInspectionCallbacks.h"
21
22
#include " swift/Sema/ConstraintSystem.h"
@@ -51,17 +52,19 @@ void typeCheckDeclAndParentClosures(ValueDecl *VD) {
51
52
TypeCheckASTNodeAtLocContext::declContext (VD->getDeclContext ()),
52
53
VD->getLoc ());
53
54
if (auto VarD = dyn_cast<VarDecl>(VD)) {
54
- // Type check any attached property wrappers so the annotated declaration
55
- // can refer to their USRs.
56
- (void )VarD->getPropertyWrapperBackingPropertyType ();
55
+ if (VarD->hasAttachedPropertyWrapper ()) {
56
+ // Type check any attached property wrappers so the annotated declaration
57
+ // can refer to their USRs.
58
+ (void )VarD->getPropertyWrapperBackingPropertyType ();
59
+ }
57
60
// Visit emitted accessors so we generated accessors from property wrappers.
58
61
VarD->visitEmittedAccessors ([&](AccessorDecl *accessor) {});
59
62
}
60
63
}
61
64
62
65
// MARK: - NodeFinderResults
63
66
64
- enum class NodeFinderResultKind { Decl };
67
+ enum class NodeFinderResultKind { Decl, Expr };
65
68
66
69
class NodeFinderResult {
67
70
NodeFinderResultKind Kind;
@@ -87,6 +90,24 @@ class NodeFinderDeclResult : public NodeFinderResult {
87
90
}
88
91
};
89
92
93
+ class NodeFinderExprResult : public NodeFinderResult {
94
+ Expr *E;
95
+ // / The \c DeclContext in which \c E occurs.
96
+ DeclContext *DC;
97
+
98
+ public:
99
+ NodeFinderExprResult (Expr *E, DeclContext *DC)
100
+ : NodeFinderResult(NodeFinderResultKind::Expr), E(E), DC(DC) {}
101
+
102
+ Expr *getExpr () const { return E; }
103
+
104
+ DeclContext *getDeclContext () const { return DC; }
105
+
106
+ static bool classof (const NodeFinderResult *Res) {
107
+ return Res->getKind () == NodeFinderResultKind::Expr;
108
+ }
109
+ };
110
+
90
111
// MARK: - NodeFinder
91
112
92
113
// / Walks the AST, looking for a node at \c LocToResolve. While walking the
@@ -192,6 +213,23 @@ class NodeFinder : ASTWalker {
192
213
}
193
214
}
194
215
216
+ if (E->getLoc () != LocToResolve) {
217
+ return Action::Continue (E);
218
+ }
219
+
220
+ switch (E->getKind ()) {
221
+ case ExprKind::DeclRef:
222
+ case ExprKind::UnresolvedDot:
223
+ case ExprKind::UnresolvedDeclRef: {
224
+ assert (Result == nullptr );
225
+ Result =
226
+ std::make_unique<NodeFinderExprResult>(E, getCurrentDeclContext ());
227
+ return Action::Stop ();
228
+ }
229
+ default :
230
+ break ;
231
+ }
232
+
195
233
return Action::Continue (E);
196
234
}
197
235
@@ -215,6 +253,57 @@ class NodeFinder : ASTWalker {
215
253
}
216
254
};
217
255
256
+ // MARK: - Solver-based expression analysis
257
+
258
+ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
259
+ public:
260
+ struct CursorInfoDeclReference {
261
+ // / If the referenced declaration is a member reference, the type of the
262
+ // / member's base, otherwise \c null.
263
+ Type BaseType;
264
+ // / Whether the reference is dynamic (see \c ide::isDynamicRef)
265
+ bool IsDynamicRef;
266
+ // / The declaration that is being referenced. Will never be \c nullptr.
267
+ ValueDecl *ReferencedDecl;
268
+ };
269
+
270
+ private:
271
+ // / The expression for which we want to provide cursor info results.
272
+ Expr *ResolveExpr;
273
+
274
+ SmallVector<CursorInfoDeclReference, 1 > Results;
275
+
276
+ void sawSolutionImpl (const Solution &S) override {
277
+ auto &CS = S.getConstraintSystem ();
278
+
279
+ auto Locator = CS.getConstraintLocator (ResolveExpr);
280
+ auto CalleeLocator = S.getCalleeLocator (Locator);
281
+ auto OverloadInfo = getSelectedOverloadInfo (S, CalleeLocator);
282
+ if (!OverloadInfo.Value ) {
283
+ // We could not resolve the referenced declaration. Skip the solution.
284
+ return ;
285
+ }
286
+
287
+ bool IsDynamicRef = false ;
288
+ auto BaseLocator =
289
+ CS.getConstraintLocator (Locator, ConstraintLocator::MemberRefBase);
290
+ if (auto BaseExpr =
291
+ simplifyLocatorToAnchor (BaseLocator).dyn_cast <Expr *>()) {
292
+ IsDynamicRef =
293
+ ide::isDynamicRef (BaseExpr, OverloadInfo.Value ,
294
+ [&S](Expr *E) { return S.getResolvedType (E); });
295
+ }
296
+
297
+ Results.push_back ({OverloadInfo.BaseTy , IsDynamicRef, OverloadInfo.Value });
298
+ }
299
+
300
+ public:
301
+ CursorInfoTypeCheckSolutionCallback (Expr *ResolveExpr)
302
+ : ResolveExpr(ResolveExpr) {}
303
+
304
+ ArrayRef<CursorInfoDeclReference> getResults () const { return Results; }
305
+ };
306
+
218
307
// MARK: - CursorInfoDoneParsingCallback
219
308
220
309
class CursorInfoDoneParsingCallback : public IDEInspectionCallbacks {
@@ -242,6 +331,59 @@ class CursorInfoDoneParsingCallback : public IDEInspectionCallbacks {
242
331
return CursorInfo;
243
332
}
244
333
334
+ std::unique_ptr<ResolvedCursorInfo>
335
+ getExprResult (NodeFinderExprResult *ExprResult, SourceFile *SrcFile,
336
+ NodeFinder &Finder) const {
337
+ Expr *E = ExprResult->getExpr ();
338
+ DeclContext *DC = ExprResult->getDeclContext ();
339
+
340
+ // Type check the statemnt containing E and listen for solutions.
341
+ CursorInfoTypeCheckSolutionCallback Callback (E);
342
+ llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
343
+ DC->getASTContext ().SolutionCallback , &Callback);
344
+ typeCheckASTNodeAtLoc (TypeCheckASTNodeAtLocContext::declContext (DC),
345
+ E->getLoc ());
346
+
347
+ if (Callback.getResults ().empty ()) {
348
+ // No results.
349
+ return nullptr ;
350
+ }
351
+
352
+ for (auto Info : Callback.getResults ()) {
353
+ // Type check the referenced decls so that all their parent closures are
354
+ // type-checked (see comment in typeCheckDeclAndParentClosures).
355
+ typeCheckDeclAndParentClosures (Info.ReferencedDecl );
356
+ }
357
+
358
+ if (Callback.getResults ().size () != 1 ) {
359
+ // FIXME: We need to be able to report multiple results.
360
+ return nullptr ;
361
+ }
362
+
363
+ // Deliver results
364
+
365
+ auto Res = Callback.getResults ()[0 ];
366
+ auto CursorInfo = std::make_unique<ResolvedValueRefCursorInfo>(
367
+ ResolvedCursorInfo (SrcFile), Res.ReferencedDecl , /* CtorTyRef=*/ nullptr ,
368
+ /* ExtTyRef=*/ nullptr , /* IsRef=*/ true , /* Ty=*/ Type (),
369
+ /* ContainerType=*/ Res.BaseType );
370
+ CursorInfo->setLoc (RequestedLoc);
371
+ CursorInfo->setIsDynamic (Res.IsDynamicRef );
372
+ if (Res.IsDynamicRef && Res.BaseType ) {
373
+ if (auto ReceiverType = Res.BaseType ->getAnyNominal ()) {
374
+ CursorInfo->setReceiverTypes ({ReceiverType});
375
+ } else if (auto MT = Res.BaseType ->getAs <AnyMetatypeType>()) {
376
+ // Look through metatypes to get the nominal type decl.
377
+ if (auto ReceiverType = MT->getInstanceType ()->getAnyNominal ()) {
378
+ CursorInfo->setReceiverTypes ({ReceiverType});
379
+ }
380
+ }
381
+ }
382
+ CursorInfo->setShorthandShadowedDecls (
383
+ Finder.getShorthandShadowedDecls (Res.ReferencedDecl ));
384
+ return CursorInfo;
385
+ }
386
+
245
387
void doneParsing (SourceFile *SrcFile) override {
246
388
if (!SrcFile) {
247
389
return ;
@@ -258,6 +400,10 @@ class CursorInfoDoneParsingCallback : public IDEInspectionCallbacks {
258
400
CursorInfo = getDeclResult (cast<NodeFinderDeclResult>(Result.get ()),
259
401
SrcFile, Finder);
260
402
break ;
403
+ case NodeFinderResultKind::Expr:
404
+ CursorInfo = getExprResult (cast<NodeFinderExprResult>(Result.get ()),
405
+ SrcFile, Finder);
406
+ break ;
261
407
}
262
408
if (Result) {
263
409
Consumer.handleResults (*CursorInfo);
0 commit comments