Skip to content

Commit b889b07

Browse files
committed
[IDE] Refactor some call related functions out of Index.cpp
The cursor info request also needs to output whether a call is "dynamic" or not, move the functions related to this out of Index.cpp and into IDE/Utils.cpp. Also cleanup the `TrailingExpr` handling in `CursorInfoResolver` - it only needs the first expression.
1 parent 8395008 commit b889b07

File tree

4 files changed

+161
-138
lines changed

4 files changed

+161
-138
lines changed

include/swift/IDE/Utils.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,23 @@ ClangNode extensionGetClangNode(const ExtensionDecl *ext);
621621
/// or a curry thunk, etc.
622622
std::pair<Type, ConcreteDeclRef> getReferencedDecl(Expr *expr);
623623

624+
/// Whether the last expression in \p ExprStack is being called.
625+
bool isBeingCalled(ArrayRef<Expr*> ExprStack);
626+
627+
/// The base of the last expression in \p ExprStack (which may look up the
628+
/// stack in eg. the case of a `DotSyntaxCallExpr`).
629+
Expr *getBase(ArrayRef<Expr *> ExprStack);
630+
631+
/// Assuming that we have a call, returns whether or not it is "dynamic" based
632+
/// on its base expression and decl of the callee. Note that this is not
633+
/// Swift's "dynamic" modifier (`ValueDecl::isDynamic`), but rathar "can call a
634+
/// function in a conformance/subclass".
635+
bool isDynamicCall(Expr *Base, ValueDecl *D);
636+
637+
/// Adds the resolved nominal types of \p Base to \p Types.
638+
void getReceiverType(Expr *Base,
639+
SmallVectorImpl<NominalTypeDecl *> &Types);
640+
624641
} // namespace ide
625642
} // namespace swift
626643

lib/IDE/IDERequests.cpp

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ class CursorInfoResolver : public SourceEntityWalker {
5959
SourceLoc LocToResolve;
6060
ResolvedCursorInfo CursorInfo;
6161
Type ContainerType;
62-
llvm::SmallVector<Expr*, 4> TrailingExprStack;
62+
Expr *OutermostCursorExpr;
6363

6464
public:
6565
explicit CursorInfoResolver(SourceFile &SrcFile) :
66-
SrcFile(SrcFile), CursorInfo(&SrcFile) {}
66+
SrcFile(SrcFile), CursorInfo(&SrcFile), OutermostCursorExpr(nullptr) {}
6767
ResolvedCursorInfo resolve(SourceLoc Loc);
6868
SourceManager &getSourceMgr() const;
6969
private:
@@ -221,44 +221,51 @@ bool CursorInfoResolver::visitDeclReference(ValueDecl *D,
221221
return !tryResolve(D, CtorTyRef, ExtTyRef, Range.getStart(), /*IsRef=*/true, T);
222222
}
223223

224+
static bool isCursorOn(Expr *E, SourceLoc Loc) {
225+
if (E->isImplicit())
226+
return false;
227+
228+
bool IsCursorOnLoc = E->getStartLoc() == Loc;
229+
// Handle cursor placement after `try` in (ForceTry|OptionalTry)Expr
230+
if (auto *FTE = dyn_cast<ForceTryExpr>(E)) {
231+
IsCursorOnLoc |= FTE->getExclaimLoc() == Loc;
232+
}
233+
if (auto *OTE = dyn_cast<OptionalTryExpr>(E)) {
234+
IsCursorOnLoc |= OTE->getQuestionLoc() == Loc;
235+
}
236+
return IsCursorOnLoc;
237+
}
238+
224239
bool CursorInfoResolver::walkToExprPre(Expr *E) {
225-
if (!isDone()) {
226-
if (auto SAE = dyn_cast<SelfApplyExpr>(E)) {
227-
if (SAE->getFn()->getStartLoc() == LocToResolve) {
228-
ContainerType = SAE->getBase()->getType();
229-
}
230-
} else if (auto ME = dyn_cast<MemberRefExpr>(E)) {
231-
SourceLoc MemberLoc = ME->getNameLoc().getBaseNameLoc();
232-
if (MemberLoc.isValid() && MemberLoc == LocToResolve) {
233-
ContainerType = ME->getBase()->getType();
234-
}
235-
}
236-
auto IsProperCursorLocation = E->getStartLoc() == LocToResolve;
237-
// Handle cursor placement after `try` in ForceTry and OptionalTry Expr.
238-
auto CheckLocation = [&IsProperCursorLocation, this](SourceLoc Loc) {
239-
IsProperCursorLocation = Loc == LocToResolve || IsProperCursorLocation;
240-
};
241-
if (auto *FTE = dyn_cast<ForceTryExpr>(E)) {
242-
CheckLocation(FTE->getExclaimLoc());
240+
if (isDone())
241+
return true;
242+
243+
if (auto SAE = dyn_cast<SelfApplyExpr>(E)) {
244+
if (SAE->getFn()->getStartLoc() == LocToResolve) {
245+
ContainerType = SAE->getBase()->getType();
243246
}
244-
if (auto *OTE = dyn_cast<OptionalTryExpr>(E)) {
245-
CheckLocation(OTE->getQuestionLoc());
247+
} else if (auto ME = dyn_cast<MemberRefExpr>(E)) {
248+
SourceLoc MemberLoc = ME->getNameLoc().getBaseNameLoc();
249+
if (MemberLoc.isValid() && MemberLoc == LocToResolve) {
250+
ContainerType = ME->getBase()->getType();
246251
}
247-
// Keep track of trailing expressions.
248-
if (!E->isImplicit() && IsProperCursorLocation)
249-
TrailingExprStack.push_back(E);
250252
}
253+
254+
if (!OutermostCursorExpr && isCursorOn(E, LocToResolve))
255+
OutermostCursorExpr = E;
256+
251257
return true;
252258
}
253259

254260
bool CursorInfoResolver::walkToExprPost(Expr *E) {
255261
if (isDone())
256262
return false;
257-
if (!TrailingExprStack.empty() && TrailingExprStack.back() == E) {
258-
// We return the outtermost expression in the token info.
259-
CursorInfo.setTrailingExpr(TrailingExprStack.front());
263+
264+
if (OutermostCursorExpr && isCursorOn(E, LocToResolve)) {
265+
CursorInfo.setTrailingExpr(OutermostCursorExpr);
260266
return false;
261267
}
268+
262269
return true;
263270
}
264271

lib/IDE/Utils.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,3 +1181,101 @@ std::pair<Type, ConcreteDeclRef> swift::ide::getReferencedDecl(Expr *expr) {
11811181

11821182
return std::make_pair(exprTy, refDecl);
11831183
}
1184+
1185+
bool swift::ide::isBeingCalled(ArrayRef<Expr *> ExprStack) {
1186+
if (ExprStack.empty())
1187+
return false;
1188+
1189+
Expr *Target = ExprStack.back();
1190+
auto UnderlyingDecl = getReferencedDecl(Target).second;
1191+
for (Expr *E: reverse(ExprStack)) {
1192+
auto *AE = dyn_cast<ApplyExpr>(E);
1193+
if (!AE || AE->isImplicit())
1194+
continue;
1195+
if (isa<ConstructorRefCallExpr>(AE) && AE->getArg() == Target)
1196+
return true;
1197+
if (isa<SelfApplyExpr>(AE))
1198+
continue;
1199+
if (getReferencedDecl(AE->getFn()).second == UnderlyingDecl)
1200+
return true;
1201+
}
1202+
return false;
1203+
}
1204+
1205+
static Expr *getContainingExpr(ArrayRef<Expr *> ExprStack, size_t index) {
1206+
if (ExprStack.size() > index)
1207+
return ExprStack.end()[-std::ptrdiff_t(index + 1)];
1208+
return nullptr;
1209+
}
1210+
1211+
Expr *swift::ide::getBase(ArrayRef<Expr *> ExprStack) {
1212+
if (ExprStack.empty())
1213+
return nullptr;
1214+
1215+
Expr *CurrentE = ExprStack.back();
1216+
Expr *ParentE = getContainingExpr(ExprStack, 1);
1217+
if (auto DSE = dyn_cast_or_null<DotSyntaxCallExpr>(ParentE))
1218+
return DSE->getBase();
1219+
else if (auto MRE = dyn_cast<MemberRefExpr>(CurrentE))
1220+
return MRE->getBase();
1221+
else if (auto SE = dyn_cast<SubscriptExpr>(CurrentE))
1222+
return SE->getBase();
1223+
return nullptr;
1224+
}
1225+
1226+
static bool isSuperRefExpr(Expr *E) {
1227+
if (!E)
1228+
return false;
1229+
if (isa<SuperRefExpr>(E))
1230+
return true;
1231+
if (auto LoadE = dyn_cast<LoadExpr>(E))
1232+
return isSuperRefExpr(LoadE->getSubExpr());
1233+
return false;
1234+
}
1235+
1236+
bool swift::ide::isDynamicCall(Expr *Base, ValueDecl *D) {
1237+
auto TyD = D->getDeclContext()->getSelfNominalTypeDecl();
1238+
if (!TyD)
1239+
return false;
1240+
if (isa<StructDecl>(TyD) || isa<EnumDecl>(TyD))
1241+
return false;
1242+
if (isSuperRefExpr(Base))
1243+
return false;
1244+
// `SomeType.staticOrClassMethod()`
1245+
if (isa<TypeExpr>(Base))
1246+
return false;
1247+
1248+
// `type(of: foo).staticOrClassMethod()`, not "dynamic" if the instance type
1249+
// is a struct/enum or if it is a class and the function is a static method
1250+
// (rather than a class method).
1251+
if (auto IT = Base->getType()->getAs<MetatypeType>()) {
1252+
auto InstanceType = IT->getInstanceType();
1253+
if (InstanceType->getStructOrBoundGenericStruct() ||
1254+
InstanceType->getEnumOrBoundGenericEnum())
1255+
return false;
1256+
if (InstanceType->getClassOrBoundGenericClass() && D->isFinal())
1257+
return false;
1258+
}
1259+
1260+
return true;
1261+
}
1262+
1263+
void swift::ide::getReceiverType(Expr *Base,
1264+
SmallVectorImpl<NominalTypeDecl *> &Types) {
1265+
Type ReceiverTy = Base->getType();
1266+
if (!ReceiverTy)
1267+
return;
1268+
1269+
if (auto LVT = ReceiverTy->getAs<LValueType>())
1270+
ReceiverTy = LVT->getObjectType();
1271+
else if (auto MetaT = ReceiverTy->getAs<MetatypeType>())
1272+
ReceiverTy = MetaT->getInstanceType();
1273+
1274+
// TODO: Handle generics and composed protocols
1275+
if (auto OpenedTy = ReceiverTy->getAs<OpenedArchetypeType>())
1276+
ReceiverTy = OpenedTy->getOpenedExistentialType();
1277+
1278+
if (auto TyD = ReceiverTy->getAnyNominal()) {
1279+
Types.push_back(TyD);
1280+
}
1281+
}

lib/Index/Index.cpp

Lines changed: 11 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/Basic/SourceManager.h"
2727
#include "swift/Basic/StringExtras.h"
2828
#include "swift/IDE/SourceEntityWalker.h"
29+
#include "swift/IDE/Utils.h"
2930
#include "swift/Markup/Markup.h"
3031
#include "swift/Sema/IDETypeChecking.h"
3132
#include "llvm/ADT/APInt.h"
@@ -1299,10 +1300,6 @@ bool IndexSwiftASTWalker::initIndexSymbol(ExtensionDecl *ExtD, ValueDecl *Extend
12991300
return false;
13001301
}
13011302

1302-
static NominalTypeDecl *getNominalParent(ValueDecl *D) {
1303-
return D->getDeclContext()->getSelfNominalTypeDecl();
1304-
}
1305-
13061303
bool IndexSwiftASTWalker::initFuncDeclIndexSymbol(FuncDecl *D,
13071304
IndexSymbol &Info) {
13081305
if (initIndexSymbol(D, D->getLoc(/*SerializedOK*/false), /*IsRef=*/false, Info))
@@ -1337,93 +1334,13 @@ bool IndexSwiftASTWalker::initFuncDeclIndexSymbol(FuncDecl *D,
13371334
return false;
13381335
}
13391336

1340-
static bool isSuperRefExpr(Expr *E) {
1341-
if (!E)
1342-
return false;
1343-
if (isa<SuperRefExpr>(E))
1344-
return true;
1345-
if (auto LoadE = dyn_cast<LoadExpr>(E))
1346-
return isSuperRefExpr(LoadE->getSubExpr());
1347-
return false;
1348-
}
1349-
1350-
static bool isDynamicCall(Expr *BaseE, ValueDecl *D) {
1351-
// "dynamic" here is not Swift's "dynamic" modifier, but rathar "can call a
1352-
// function in a conformance/subclass". Eg. if the receiver is "super", an
1353-
// extension may have injected itself in the parent hierarchy - this call
1354-
// would not be "dynamic" for our purposes (though would be Swift's
1355-
// "dynamic"), but it is also not statically determined.
1356-
auto TyD = getNominalParent(D);
1357-
if (!TyD)
1358-
return false;
1359-
if (isa<StructDecl>(TyD) || isa<EnumDecl>(TyD))
1360-
return false;
1361-
if (isSuperRefExpr(BaseE))
1362-
return false;
1363-
// `SomeType.staticOrClassMethod()`
1364-
if (isa<TypeExpr>(BaseE))
1365-
return false;
1366-
1367-
// `type(of: foo).staticOrClassMethod()`, not "dynamic" if the instance type
1368-
// is a struct/enum or if it is a class and the function is a static method
1369-
// (rather than a class method).
1370-
if (auto IT = BaseE->getType()->getAs<MetatypeType>()) {
1371-
auto InstanceType = IT->getInstanceType();
1372-
if (InstanceType->getStructOrBoundGenericStruct() ||
1373-
InstanceType->getEnumOrBoundGenericEnum())
1374-
return false;
1375-
if (InstanceType->getClassOrBoundGenericClass() && D->isFinal())
1376-
return false;
1377-
}
1378-
1379-
return true;
1380-
}
1381-
1382-
static Expr *getUnderlyingFunc(Expr *Fn) {
1383-
Fn = Fn->getSemanticsProvidingExpr();
1384-
if (auto *DRE = dyn_cast<DeclRefExpr>(Fn))
1385-
return DRE;
1386-
if (auto ApplyE = dyn_cast<SelfApplyExpr>(Fn))
1387-
return getUnderlyingFunc(ApplyE->getFn());
1388-
if (auto *ACE = dyn_cast<AutoClosureExpr>(Fn)) {
1389-
if (auto *Unwrapped = ACE->getUnwrappedCurryThunkExpr())
1390-
return getUnderlyingFunc(Unwrapped);
1391-
}
1392-
return Fn;
1393-
}
1394-
1395-
static bool isBeingCalled(Expr *Target, ArrayRef<Expr*> ExprStack) {
1396-
if (!Target)
1397-
return false;
1398-
Target = getUnderlyingFunc(Target);
1399-
1400-
for (Expr *E: reverse(ExprStack)) {
1401-
auto *AE = dyn_cast<ApplyExpr>(E);
1402-
if (!AE || AE->isImplicit())
1403-
continue;
1404-
if (isa<ConstructorRefCallExpr>(AE) && AE->getArg() == Target)
1405-
return true;
1406-
if (isa<SelfApplyExpr>(AE))
1407-
continue;
1408-
if (getUnderlyingFunc(AE->getFn()) == Target)
1409-
return true;
1410-
}
1411-
return false;
1412-
}
1413-
14141337
bool IndexSwiftASTWalker::initFuncRefIndexSymbol(ValueDecl *D, SourceLoc Loc,
14151338
IndexSymbol &Info) {
14161339

14171340
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
14181341
return true;
14191342

1420-
Expr *CurrentE = getCurrentExpr();
1421-
if (!CurrentE)
1422-
return false;
1423-
1424-
Expr *ParentE = getParentExpr();
1425-
1426-
if (!isa<AbstractStorageDecl>(D) && !isBeingCalled(CurrentE, ExprStack))
1343+
if (!isa<AbstractStorageDecl>(D) && !ide::isBeingCalled(ExprStack))
14271344
return false;
14281345

14291346
Info.roles |= (unsigned)SymbolRole::Call;
@@ -1432,36 +1349,20 @@ bool IndexSwiftASTWalker::initFuncRefIndexSymbol(ValueDecl *D, SourceLoc Loc,
14321349
return true;
14331350
}
14341351

1435-
Expr *BaseE = nullptr;
1436-
if (auto DotE = dyn_cast_or_null<DotSyntaxCallExpr>(ParentE))
1437-
BaseE = DotE->getBase();
1438-
else if (auto MembE = dyn_cast<MemberRefExpr>(CurrentE))
1439-
BaseE = MembE->getBase();
1440-
else if (auto SubsE = dyn_cast<SubscriptExpr>(CurrentE))
1441-
BaseE = SubsE->getBase();
1442-
1443-
if (!BaseE || BaseE == CurrentE)
1352+
Expr *BaseE = ide::getBase(ExprStack);
1353+
if (!BaseE)
14441354
return false;
14451355

1446-
if (isDynamicCall(BaseE, D))
1356+
if (ide::isDynamicCall(BaseE, D))
14471357
Info.roles |= (unsigned)SymbolRole::Dynamic;
14481358

1449-
if (Type ReceiverTy = BaseE->getType()) {
1450-
if (auto LVT = ReceiverTy->getAs<LValueType>())
1451-
ReceiverTy = LVT->getObjectType();
1452-
else if (auto MetaT = ReceiverTy->getAs<MetatypeType>())
1453-
ReceiverTy = MetaT->getInstanceType();
1454-
1455-
// TODO: Handle generics and composed protocols
1456-
if (auto OpenedTy = ReceiverTy->getAs<OpenedArchetypeType>())
1457-
ReceiverTy = OpenedTy->getOpenedExistentialType();
1458-
1459-
if (auto TyD = ReceiverTy->getAnyNominal()) {
1460-
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationReceivedBy, TyD))
1461-
return true;
1462-
}
1359+
SmallVector<NominalTypeDecl *, 1> Types;
1360+
ide::getReceiverType(BaseE, Types);
1361+
for (auto *ReceiverTy : Types) {
1362+
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationReceivedBy,
1363+
ReceiverTy))
1364+
return true;
14631365
}
1464-
14651366
return false;
14661367
}
14671368

0 commit comments

Comments
 (0)