Skip to content

Commit 166d388

Browse files
authored
RangeInfo: stuff a bit about whether the selected range exits. (#9389)
1 parent 1d70565 commit 166d388

File tree

4 files changed

+56
-16
lines changed

4 files changed

+56
-16
lines changed

include/swift/IDE/Utils.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef SWIFT_IDE_UTILS_H
1414
#define SWIFT_IDE_UTILS_H
1515

16+
#include "llvm/ADT/PointerIntPair.h"
1617
#include "swift/Basic/LLVM.h"
1718
#include "swift/AST/ASTNode.h"
1819
#include "swift/AST/Module.h"
@@ -243,9 +244,12 @@ enum class OrphanKind : int8_t {
243244
Break,
244245
Continue,
245246
};
247+
248+
typedef llvm::PointerIntPair<TypeBase*, 1, bool> ReturnTyAndWhetherExit;
249+
246250
struct ResolvedRangeInfo {
247251
RangeKind Kind;
248-
Type Ty;
252+
ReturnTyAndWhetherExit ExitInfo;
249253
StringRef Content;
250254
bool HasSingleEntry;
251255
bool ThrowingUnhandledError;
@@ -256,23 +260,26 @@ struct ResolvedRangeInfo {
256260
ArrayRef<DeclaredDecl> DeclaredDecls;
257261
ArrayRef<ReferencedDecl> ReferencedDecls;
258262
DeclContext* RangeContext;
259-
ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content,
263+
ResolvedRangeInfo(RangeKind Kind, ReturnTyAndWhetherExit ExitInfo, StringRef Content,
260264
DeclContext* RangeContext,
261265
bool HasSingleEntry, bool ThrowingUnhandledError,
262266
OrphanKind Orphan, ArrayRef<ASTNode> ContainedNodes,
263267
ArrayRef<DeclaredDecl> DeclaredDecls,
264268
ArrayRef<ReferencedDecl> ReferencedDecls): Kind(Kind),
265-
Ty(Ty), Content(Content), HasSingleEntry(HasSingleEntry),
269+
ExitInfo(ExitInfo), Content(Content),
270+
HasSingleEntry(HasSingleEntry),
266271
ThrowingUnhandledError(ThrowingUnhandledError),
267272
Orphan(Orphan), ContainedNodes(ContainedNodes),
268273
DeclaredDecls(DeclaredDecls),
269274
ReferencedDecls(ReferencedDecls),
270275
RangeContext(RangeContext) {}
271276
ResolvedRangeInfo(StringRef Content) :
272-
ResolvedRangeInfo(RangeKind::Invalid, Type(), Content, nullptr,
277+
ResolvedRangeInfo(RangeKind::Invalid, {nullptr, false}, Content, nullptr,
273278
/*Single entry*/true, /*unhandled error*/false,
274279
OrphanKind::None, {}, {}, {}) {}
275280
void print(llvm::raw_ostream &OS);
281+
bool exit() const { return ExitInfo.getInt(); }
282+
Type getType() const { return ExitInfo.getPointer(); }
276283
};
277284

278285
class RangeResolver : public SourceEntityWalker {

lib/IDE/SwiftSourceDocInfo.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,15 @@ void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
227227
OS << "</Kind>\n";
228228

229229
OS << "<Content>" << Content << "</Content>\n";
230-
if (Ty) {
230+
231+
if (auto Ty = ExitInfo.getPointer()) {
231232
OS << "<Type>";
232233
Ty->print(OS);
233-
OS << "</Type>\n";
234+
OS << "</Type>";
235+
if (ExitInfo.getInt()) {
236+
OS << "<Exit>true</Exit>";
237+
}
238+
OS << "\n";
234239
}
235240

236241
if (RangeContext) {
@@ -382,25 +387,29 @@ struct RangeResolver::Implementation {
382387
std::vector<ASTNode> ContainedASTNodes;
383388

384389
/// Collect the type that an ASTNode should be evaluated to.
385-
Type resolveNodeType(ASTNode N, RangeKind Kind) {
386-
auto VoidTy = Ctx.getVoidDecl()->getDeclaredInterfaceType();
390+
ReturnTyAndWhetherExit resolveNodeType(ASTNode N, RangeKind Kind) {
391+
auto *VoidTy = Ctx.getVoidDecl()->getDeclaredInterfaceType().getPointer();
387392
if (N.isNull())
388-
return VoidTy;
393+
return {VoidTy, false};
389394
switch(Kind) {
390395
case RangeKind::Invalid:
391396
case RangeKind::SingleDecl:
392397
llvm_unreachable("cannot get type.");
393398

394399
// For a single expression, its type is apparent.
395400
case RangeKind::SingleExpression:
396-
return N.get<Expr*>()->getType();
401+
return {N.get<Expr*>()->getType().getPointer(), false};
397402

398403
// For statements, we either resolve to the returning type or Void.
399404
case RangeKind::SingleStatement:
400405
case RangeKind::MultiStatement: {
401406
if (N.is<Stmt*>()) {
402407
if (auto RS = dyn_cast<ReturnStmt>(N.get<Stmt*>())) {
403-
return resolveNodeType(RS->getResult(), RangeKind::SingleExpression);
408+
return {
409+
resolveNodeType(RS->hasResult() ? RS->getResult() : nullptr,
410+
RangeKind::SingleExpression).getPointer(),
411+
true
412+
};
404413
}
405414

406415
// Unbox the brace statement to find its type.
@@ -419,15 +428,16 @@ struct RangeResolver::Implementation {
419428
RangeKind::SingleStatement);
420429

421430
// If two branches agree on the return type, return that type.
422-
if (ThenTy->isEqual(ElseTy))
431+
if (ThenTy.getPointer()->isEqual(ElseTy.getPointer()) &&
432+
ThenTy.getInt() == ElseTy.getInt())
423433
return ThenTy;
424434

425435
// Otherwise, return the error type.
426-
return Ctx.TheErrorType;
436+
return {Ctx.TheErrorType.getPointer(), false};
427437
}
428438
}
429439
// For other statements, the type should be void.
430-
return VoidTy;
440+
return {VoidTy, false};
431441
}
432442
}
433443
}
@@ -458,7 +468,7 @@ struct RangeResolver::Implementation {
458468
llvm::makeArrayRef(ReferencedDecls));
459469
else {
460470
assert(Node.is<Decl*>());
461-
return ResolvedRangeInfo(RangeKind::SingleDecl, Type(), Content,
471+
return ResolvedRangeInfo(RangeKind::SingleDecl, {nullptr, false}, Content,
462472
getImmediateContext(), SingleEntry,
463473
UnhandledError, Kind,
464474
llvm::makeArrayRef(ContainedASTNodes),

test/IDE/range_info_branches.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,31 @@ func foo(_ a: Bool) -> Int{
1010
}
1111
}
1212

13+
func foo1(_ a: Bool) {
14+
if a {}
15+
if a {}
16+
else {}
17+
if a {
18+
return
19+
} else {
20+
return
21+
}
22+
}
23+
1324
// RUN: %target-swift-ide-test -range -pos=2:1 -end-pos 5:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-ERR
1425
// RUN: %target-swift-ide-test -range -pos=6:1 -end-pos 10:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-INT
26+
// RUN: %target-swift-ide-test -range -pos=14:1 -end-pos 14:10 -source-filename %s | %FileCheck %s -check-prefix=CHECK-VOID-NO-RETURN
27+
// RUN: %target-swift-ide-test -range -pos=15:1 -end-pos 16:10 -source-filename %s | %FileCheck %s -check-prefix=CHECK-VOID-NO-RETURN
28+
// RUN: %target-swift-ide-test -range -pos=17:1 -end-pos 21:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-VOID-RETURN
1529

1630
// CHECK-ERR: <Type><<error type>></Type>
31+
// CHECK-ERR-NOT: <Exit>true</Exit>
32+
1733
// CHECK-INT: <Type>Int</Type>
34+
// CHECK-INT: <Exit>true</Exit>
35+
36+
// CHECK-VOID-NO-RETURN: <Type>Void</Type>
37+
// CHECK-VOID-NO-RETURN-NOT: <Exit>true</Exit>
38+
39+
// CHECK-VOID-RETURN: <Type>Void</Type>
40+
// CHECK-VOID-RETURN: <Exit>true</Exit>

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,7 @@ static void resolveRange(SwiftLangSupport &Lang,
13371337
case RangeKind::SingleExpression: {
13381338
SmallString<64> SS;
13391339
llvm::raw_svector_ostream OS(SS);
1340-
Info.Ty.print(OS);
1340+
Info.ExitInfo.getPointer()->print(OS);
13411341
Result.ExprType = OS.str();
13421342
Receiver(Result);
13431343
return;

0 commit comments

Comments
 (0)