@@ -1151,6 +1151,66 @@ fillSymbolInfo(CursorSymbolInfo &Symbol, const DeclInfo &DInfo,
11511151 return llvm::Error::success ();
11521152}
11531153
1154+ // If \p E is a literal, returns the declaration that should be reported by
1155+ // cursor info for that initializer.
1156+ static ValueDecl *getCursorInfoDeclForLiteral (Expr *E) {
1157+ if (auto *CollectionLit = dyn_cast<CollectionExpr>(E)) {
1158+ return CollectionLit->getInitializer ().getDecl ();
1159+ }
1160+
1161+ LiteralExpr* LitExpr = dyn_cast<LiteralExpr>(E);
1162+ if (!LitExpr) {
1163+ return nullptr ;
1164+ }
1165+
1166+ bool IsObjectLiteral = isa<ObjectLiteralExpr>(E);
1167+ if (!IsObjectLiteral && LitExpr->getInitializer ().getDecl ()) {
1168+ return LitExpr->getInitializer ().getDecl ();
1169+ }
1170+
1171+ // We shouldn’t report the builtin initializer to the user because it’s
1172+ // underscored and not visible. Instead, return the type of the literal.
1173+ if (IsObjectLiteral || isa<BuiltinLiteralExpr>(E)) {
1174+ Type Ty = E->getType ();
1175+ if (!Ty) {
1176+ return nullptr ;
1177+ }
1178+ auto NominalTy = Ty->getAs <NominalOrBoundGenericNominalType>();
1179+ if (!NominalTy) {
1180+ return nullptr ;
1181+ }
1182+ return NominalTy->getDecl ();
1183+ }
1184+ return nullptr ;
1185+ }
1186+
1187+ static bool addCursorInfoForLiteral (
1188+ CursorInfoData &Data, Expr *LitExpr, SwiftLangSupport &Lang,
1189+ const CompilerInvocation &CompInvoc, SourceLoc CursorLoc,
1190+ ArrayRef<ImmutableTextSnapshotRef> PreviousSnaps) {
1191+ if (!LitExpr) {
1192+ return false ;
1193+ }
1194+
1195+ ValueDecl *Decl = getCursorInfoDeclForLiteral (LitExpr);
1196+ if (!Decl) {
1197+ return false ;
1198+ }
1199+
1200+ auto &Symbol = Data.Symbols .emplace_back ();
1201+ DeclInfo Info (Decl, nullptr , true , false , {}, CompInvoc);
1202+ auto Err = fillSymbolInfo (Symbol, Info, CursorLoc, false , Lang, CompInvoc,
1203+ PreviousSnaps, Data.Allocator );
1204+
1205+ bool Success = true ;
1206+ llvm::handleAllErrors (std::move (Err), [&](const llvm::StringError &E) {
1207+ Data.InternalDiagnostic = copyCString (E.getMessage (), Data.Allocator );
1208+ Data.Symbols .pop_back ();
1209+ Success = false ;
1210+ });
1211+ return Success;
1212+ }
1213+
11541214static bool
11551215addCursorInfoForDecl (CursorInfoData &Data, ResolvedValueRefCursorInfoPtr Info,
11561216 bool AddRefactorings, bool AddSymbolGraph,
@@ -1202,7 +1262,8 @@ addCursorInfoForDecl(CursorInfoData &Data, ResolvedValueRefCursorInfoPtr Info,
12021262 fillSymbolInfo (SymbolInfo, DInfo, Info->getLoc (), AddSymbolGraph,
12031263 Lang, Invoc, PreviousSnaps, Data.Allocator )) {
12041264 // Ignore but make sure to remove the partially-filled symbol
1205- llvm::handleAllErrors (std::move (Err), [](const llvm::StringError &E) {});
1265+ llvm::handleAllErrors (std::move (Err),
1266+ [](const llvm::StringError &E) {});
12061267 Data.Symbols .pop_back ();
12071268 }
12081269 }
@@ -1630,21 +1691,40 @@ static void resolveCursor(
16301691 }
16311692 case CursorInfoKind::ExprStart:
16321693 case CursorInfoKind::StmtStart: {
1694+ // If code under cursor is literal expression returns Expr,
1695+ // otherwise nullptr.
1696+ auto tryGetLiteralExpr = [](auto CI) -> Expr * {
1697+ auto *ExprInfo = dyn_cast<ResolvedExprStartCursorInfo>(CI);
1698+ if (!ExprInfo || !ExprInfo->getTrailingExpr ()) {
1699+ return nullptr ;
1700+ }
1701+ Expr *E = ExprInfo->getTrailingExpr ();
1702+ if (dyn_cast<LiteralExpr>(E) || dyn_cast<CollectionExpr>(E)) {
1703+ return E;
1704+ }
1705+ return nullptr ;
1706+ };
1707+
1708+ CursorInfoData Data;
1709+
16331710 if (Actionables) {
16341711 addRefactorings (
16351712 Actions, collectRefactorings (CursorInfo, /* ExcludeRename=*/ true ));
1636- if (!Actions.empty ()) {
1637- CursorInfoData Data;
1638- Data.AvailableActions = Actions;
1639- Receiver (RequestResult<CursorInfoData>::fromResult (Data));
1640- return ;
1641- }
1713+ Data.AvailableActions = Actions;
16421714 }
16431715
1644- CursorInfoData Info;
1645- Info.InternalDiagnostic =
1646- " Resolved to incomplete expression or statement." ;
1647- Receiver (RequestResult<CursorInfoData>::fromResult (Info));
1716+ // Handle literal expression.
1717+ if (auto *LitExpr = tryGetLiteralExpr (CursorInfo)) {
1718+ addCursorInfoForLiteral (Data, LitExpr, Lang, CompInvok,
1719+ CursorInfo->getLoc (), getPreviousASTSnaps ());
1720+ }
1721+
1722+ if (Data.isEmpty ()) {
1723+ Data.InternalDiagnostic =
1724+ " Resolved to incomplete expression or statement." ;
1725+ }
1726+
1727+ Receiver (RequestResult<CursorInfoData>::fromResult (Data));
16481728 return ;
16491729 }
16501730 case CursorInfoKind::Invalid:
0 commit comments