1616#include " swift/AST/GenericEnvironment.h"
1717#include " swift/AST/NameLookup.h"
1818#include " swift/AST/USRGeneration.h"
19+ #include " swift/IDE/SelectedOverloadInfo.h"
1920#include " swift/IDE/TypeCheckCompletionCallback.h"
2021#include " swift/Parse/IDEInspectionCallbacks.h"
2122#include " swift/Sema/ConstraintSystem.h"
@@ -47,21 +48,28 @@ void typeCheckDeclAndParentClosures(ValueDecl *VD) {
4748 DC = DC->getParent ();
4849 }
4950
50- typeCheckASTNodeAtLoc (
51- TypeCheckASTNodeAtLocContext::declContext (VD->getDeclContext ()),
52- VD->getLoc ());
51+ if (!VD->getInterfaceType ()) {
52+ // The decl has an interface time if it came from another module. In that
53+ // case, there's nothing to do. Otherwise, type check the decl to get its
54+ // type.
55+ typeCheckASTNodeAtLoc (
56+ TypeCheckASTNodeAtLocContext::declContext (VD->getDeclContext ()),
57+ VD->getLoc ());
58+ }
5359 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 ();
60+ if (VarD->hasAttachedPropertyWrapper ()) {
61+ // Type check any attached property wrappers so the annotated declaration
62+ // can refer to their USRs.
63+ (void )VarD->getPropertyWrapperBackingPropertyType ();
64+ }
5765 // Visit emitted accessors so we generated accessors from property wrappers.
5866 VarD->visitEmittedAccessors ([&](AccessorDecl *accessor) {});
5967 }
6068}
6169
6270// MARK: - NodeFinderResults
6371
64- enum class NodeFinderResultKind { Decl };
72+ enum class NodeFinderResultKind { Decl, Expr };
6573
6674class NodeFinderResult {
6775 NodeFinderResultKind Kind;
@@ -87,6 +95,24 @@ class NodeFinderDeclResult : public NodeFinderResult {
8795 }
8896};
8997
98+ class NodeFinderExprResult : public NodeFinderResult {
99+ Expr *E;
100+ // / The \c DeclContext in which \c E occurs.
101+ DeclContext *DC;
102+
103+ public:
104+ NodeFinderExprResult (Expr *E, DeclContext *DC)
105+ : NodeFinderResult(NodeFinderResultKind::Expr), E(E), DC(DC) {}
106+
107+ Expr *getExpr () const { return E; }
108+
109+ DeclContext *getDeclContext () const { return DC; }
110+
111+ static bool classof (const NodeFinderResult *Res) {
112+ return Res->getKind () == NodeFinderResultKind::Expr;
113+ }
114+ };
115+
90116// MARK: - NodeFinder
91117
92118// / Walks the AST, looking for a node at \c LocToResolve. While walking the
@@ -192,6 +218,23 @@ class NodeFinder : ASTWalker {
192218 }
193219 }
194220
221+ if (E->getLoc () != LocToResolve) {
222+ return Action::Continue (E);
223+ }
224+
225+ switch (E->getKind ()) {
226+ case ExprKind::DeclRef:
227+ case ExprKind::UnresolvedDot:
228+ case ExprKind::UnresolvedDeclRef: {
229+ assert (Result == nullptr );
230+ Result =
231+ std::make_unique<NodeFinderExprResult>(E, getCurrentDeclContext ());
232+ return Action::Stop ();
233+ }
234+ default :
235+ break ;
236+ }
237+
195238 return Action::Continue (E);
196239 }
197240
@@ -215,6 +258,57 @@ class NodeFinder : ASTWalker {
215258 }
216259};
217260
261+ // MARK: - Solver-based expression analysis
262+
263+ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
264+ public:
265+ struct CursorInfoDeclReference {
266+ // / If the referenced declaration is a member reference, the type of the
267+ // / member's base, otherwise \c null.
268+ Type BaseType;
269+ // / Whether the reference is dynamic (see \c ide::isDynamicRef)
270+ bool IsDynamicRef;
271+ // / The declaration that is being referenced. Will never be \c nullptr.
272+ ValueDecl *ReferencedDecl;
273+ };
274+
275+ private:
276+ // / The expression for which we want to provide cursor info results.
277+ Expr *ResolveExpr;
278+
279+ SmallVector<CursorInfoDeclReference, 1 > Results;
280+
281+ void sawSolutionImpl (const Solution &S) override {
282+ auto &CS = S.getConstraintSystem ();
283+
284+ auto Locator = CS.getConstraintLocator (ResolveExpr);
285+ auto CalleeLocator = S.getCalleeLocator (Locator);
286+ auto OverloadInfo = getSelectedOverloadInfo (S, CalleeLocator);
287+ if (!OverloadInfo.Value ) {
288+ // We could not resolve the referenced declaration. Skip the solution.
289+ return ;
290+ }
291+
292+ bool IsDynamicRef = false ;
293+ auto BaseLocator =
294+ CS.getConstraintLocator (Locator, ConstraintLocator::MemberRefBase);
295+ if (auto BaseExpr =
296+ simplifyLocatorToAnchor (BaseLocator).dyn_cast <Expr *>()) {
297+ IsDynamicRef =
298+ ide::isDynamicRef (BaseExpr, OverloadInfo.Value ,
299+ [&S](Expr *E) { return S.getResolvedType (E); });
300+ }
301+
302+ Results.push_back ({OverloadInfo.BaseTy , IsDynamicRef, OverloadInfo.Value });
303+ }
304+
305+ public:
306+ CursorInfoTypeCheckSolutionCallback (Expr *ResolveExpr)
307+ : ResolveExpr(ResolveExpr) {}
308+
309+ ArrayRef<CursorInfoDeclReference> getResults () const { return Results; }
310+ };
311+
218312// MARK: - CursorInfoDoneParsingCallback
219313
220314class CursorInfoDoneParsingCallback : public IDEInspectionCallbacks {
@@ -242,6 +336,59 @@ class CursorInfoDoneParsingCallback : public IDEInspectionCallbacks {
242336 return CursorInfo;
243337 }
244338
339+ std::unique_ptr<ResolvedCursorInfo>
340+ getExprResult (NodeFinderExprResult *ExprResult, SourceFile *SrcFile,
341+ NodeFinder &Finder) const {
342+ Expr *E = ExprResult->getExpr ();
343+ DeclContext *DC = ExprResult->getDeclContext ();
344+
345+ // Type check the statemnt containing E and listen for solutions.
346+ CursorInfoTypeCheckSolutionCallback Callback (E);
347+ llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
348+ DC->getASTContext ().SolutionCallback , &Callback);
349+ typeCheckASTNodeAtLoc (TypeCheckASTNodeAtLocContext::declContext (DC),
350+ E->getLoc ());
351+
352+ if (Callback.getResults ().empty ()) {
353+ // No results.
354+ return nullptr ;
355+ }
356+
357+ for (auto Info : Callback.getResults ()) {
358+ // Type check the referenced decls so that all their parent closures are
359+ // type-checked (see comment in typeCheckDeclAndParentClosures).
360+ typeCheckDeclAndParentClosures (Info.ReferencedDecl );
361+ }
362+
363+ if (Callback.getResults ().size () != 1 ) {
364+ // FIXME: We need to be able to report multiple results.
365+ return nullptr ;
366+ }
367+
368+ // Deliver results
369+
370+ auto Res = Callback.getResults ()[0 ];
371+ auto CursorInfo = std::make_unique<ResolvedValueRefCursorInfo>(
372+ ResolvedCursorInfo (SrcFile), Res.ReferencedDecl , /* CtorTyRef=*/ nullptr ,
373+ /* ExtTyRef=*/ nullptr , /* IsRef=*/ true , /* Ty=*/ Type (),
374+ /* ContainerType=*/ Res.BaseType );
375+ CursorInfo->setLoc (RequestedLoc);
376+ CursorInfo->setIsDynamic (Res.IsDynamicRef );
377+ if (Res.IsDynamicRef && Res.BaseType ) {
378+ if (auto ReceiverType = Res.BaseType ->getAnyNominal ()) {
379+ CursorInfo->setReceiverTypes ({ReceiverType});
380+ } else if (auto MT = Res.BaseType ->getAs <AnyMetatypeType>()) {
381+ // Look through metatypes to get the nominal type decl.
382+ if (auto ReceiverType = MT->getInstanceType ()->getAnyNominal ()) {
383+ CursorInfo->setReceiverTypes ({ReceiverType});
384+ }
385+ }
386+ }
387+ CursorInfo->setShorthandShadowedDecls (
388+ Finder.getShorthandShadowedDecls (Res.ReferencedDecl ));
389+ return CursorInfo;
390+ }
391+
245392 void doneParsing (SourceFile *SrcFile) override {
246393 if (!SrcFile) {
247394 return ;
@@ -258,6 +405,10 @@ class CursorInfoDoneParsingCallback : public IDEInspectionCallbacks {
258405 CursorInfo = getDeclResult (cast<NodeFinderDeclResult>(Result.get ()),
259406 SrcFile, Finder);
260407 break ;
408+ case NodeFinderResultKind::Expr:
409+ CursorInfo = getExprResult (cast<NodeFinderExprResult>(Result.get ()),
410+ SrcFile, Finder);
411+ break ;
261412 }
262413 if (Result) {
263414 Consumer.handleResults (*CursorInfo);
0 commit comments