Skip to content

Commit e7a16bf

Browse files
authored
[RangeInfo] Include a boolean value in the resolved range info to indicate whether the given range has more than one entry point. (#7150)
A classic multi-entry range is several case statements.
1 parent bdbd059 commit e7a16bf

File tree

3 files changed

+76
-6
lines changed

3 files changed

+76
-6
lines changed

include/swift/IDE/Utils.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ struct ResolvedRangeInfo {
227227
RangeKind Kind;
228228
Type Ty;
229229
StringRef Content;
230+
bool HasSingleEntry;
230231

231232
// The topmost ast nodes contained in the given range.
232233
ArrayRef<ASTNode> ContainedNodes;
@@ -235,15 +236,18 @@ struct ResolvedRangeInfo {
235236
DeclContext* RangeContext;
236237
ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content,
237238
DeclContext* RangeContext,
239+
bool HasSingleEntry,
238240
ArrayRef<ASTNode> ContainedNodes,
239241
ArrayRef<DeclaredDecl> DeclaredDecls,
240242
ArrayRef<ReferencedDecl> ReferencedDecls): Kind(Kind),
241-
Ty(Ty), Content(Content), ContainedNodes(ContainedNodes),
243+
Ty(Ty), Content(Content), HasSingleEntry(HasSingleEntry),
244+
ContainedNodes(ContainedNodes),
242245
DeclaredDecls(DeclaredDecls),
243246
ReferencedDecls(ReferencedDecls),
244247
RangeContext(RangeContext) {}
245248
ResolvedRangeInfo() :
246-
ResolvedRangeInfo(RangeKind::Invalid, Type(), StringRef(), nullptr, {}, {}, {}) {}
249+
ResolvedRangeInfo(RangeKind::Invalid, Type(), StringRef(), nullptr,
250+
/*Single entry*/true, {}, {}, {}) {}
247251
void print(llvm::raw_ostream &OS);
248252
};
249253

lib/IDE/SwiftSourceDocInfo.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
211211
printContext(OS, RangeContext);
212212
OS << "</Context>\n";
213213

214+
if (!HasSingleEntry) {
215+
OS << "<Entry>Multi</Entry>\n";
216+
}
217+
214218
for (auto &VD : DeclaredDecls) {
215219
OS << "<Declared>" << VD.VD->getNameStr() << "</Declared>";
216220
OS << "<OutscopeReference>";
@@ -296,23 +300,25 @@ struct RangeResolver::Implementation {
296300
ResolvedRangeInfo getSingleNodeKind(ASTNode Node) {
297301
assert(!Node.isNull());
298302
assert(ContainedASTNodes.size() == 1);
303+
// Single node implies single entry point, or is it?
304+
bool SingleEntry = true;
299305
if (Node.is<Expr*>())
300306
return ResolvedRangeInfo(RangeKind::SingleExpression,
301307
resolveNodeType(Node), Content,
302-
getImmediateContext(),
308+
getImmediateContext(), SingleEntry,
303309
llvm::makeArrayRef(ContainedASTNodes),
304310
llvm::makeArrayRef(DeclaredDecls),
305311
llvm::makeArrayRef(ReferencedDecls));
306312
else if (Node.is<Stmt*>())
307313
return ResolvedRangeInfo(RangeKind::SingleStatement, resolveNodeType(Node),
308-
Content, getImmediateContext(),
314+
Content, getImmediateContext(), SingleEntry,
309315
llvm::makeArrayRef(ContainedASTNodes),
310316
llvm::makeArrayRef(DeclaredDecls),
311317
llvm::makeArrayRef(ReferencedDecls));
312318
else {
313319
assert(Node.is<Decl*>());
314320
return ResolvedRangeInfo(RangeKind::SingleDecl, Type(), Content,
315-
getImmediateContext(),
321+
getImmediateContext(), SingleEntry,
316322
llvm::makeArrayRef(ContainedASTNodes),
317323
llvm::makeArrayRef(DeclaredDecls),
318324
llvm::makeArrayRef(ReferencedDecls));
@@ -486,6 +492,22 @@ struct RangeResolver::Implementation {
486492
FurtherReferenceWalker(this).walk(getImmediateContext());
487493
}
488494

495+
bool hasSingleEntryPoint(ArrayRef<ASTNode> Nodes) {
496+
unsigned CaseCount = 0;
497+
// Count the number of case/default statements.
498+
for (auto N : Nodes) {
499+
if (Stmt *S = N.is<Stmt*>() ? N.get<Stmt*>() : nullptr) {
500+
if (S->getKind() == StmtKind::Case)
501+
CaseCount ++;
502+
}
503+
}
504+
// If there are more than one case/default statements, there are more than
505+
// one entry point.
506+
if (CaseCount > 1)
507+
return false;
508+
return true;
509+
}
510+
489511
void analyze(ASTNode Node) {
490512
Decl *D = Node.is<Decl*>() ? Node.get<Decl*>() : nullptr;
491513
analyzeDecl(D);
@@ -529,7 +551,7 @@ struct RangeResolver::Implementation {
529551
Result = {RangeKind::MultiStatement,
530552
/* Last node has the type */
531553
resolveNodeType(DCInfo.EndMatches.back()), Content,
532-
getImmediateContext(),
554+
getImmediateContext(), hasSingleEntryPoint(ContainedASTNodes),
533555
llvm::makeArrayRef(ContainedASTNodes),
534556
llvm::makeArrayRef(DeclaredDecls),
535557
llvm::makeArrayRef(ReferencedDecls)};

test/IDE/range_info_basics.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ func foo6() -> Int {
7171
return a
7272
}
7373

74+
func foo7(a : Int) -> Int {
75+
switch a {
76+
case 1:
77+
return 0
78+
case 2:
79+
return 1
80+
default:
81+
return a
82+
}
83+
}
84+
7485
// RUN: %target-swift-ide-test -range -pos=8:1 -end-pos 8:32 -source-filename %s | %FileCheck %s -check-prefix=CHECK1
7586
// RUN: %target-swift-ide-test -range -pos=9:1 -end-pos 9:26 -source-filename %s | %FileCheck %s -check-prefix=CHECK2
7687
// RUN: %target-swift-ide-test -range -pos=10:1 -end-pos 10:27 -source-filename %s | %FileCheck %s -check-prefix=CHECK3
@@ -88,6 +99,9 @@ func foo6() -> Int {
8899
// RUN: %target-swift-ide-test -range -pos=63:1 -end-pos=66:44 -source-filename %s | %FileCheck %s -check-prefix=CHECK15
89100
// RUN: %target-swift-ide-test -range -pos=63:1 -end-pos=68:15 -source-filename %s | %FileCheck %s -check-prefix=CHECK16
90101
// RUN: %target-swift-ide-test -range -pos=67:1 -end-pos=67:19 -source-filename %s | %FileCheck %s -check-prefix=CHECK17
102+
// RUN: %target-swift-ide-test -range -pos=76:1 -end-pos=79:13 -source-filename %s | %FileCheck %s -check-prefix=CHECK18
103+
// RUN: %target-swift-ide-test -range -pos=76:1 -end-pos=77:13 -source-filename %s | %FileCheck %s -check-prefix=CHECK19
104+
// RUN: %target-swift-ide-test -range -pos=78:1 -end-pos=81:13 -source-filename %s | %FileCheck %s -check-prefix=CHECK20
91105

92106
// CHECK1: <Kind>SingleDecl</Kind>
93107
// CHECK1-NEXT: <Content>func foo1() -> Int { return 0 }</Content>
@@ -312,3 +326,33 @@ func foo6() -> Int {
312326
// CHECK17-NEXT: <Referenced>c</Referenced><Type>Int</Type>
313327
// CHECK17-NEXT: <ASTNodes>1</ASTNodes>
314328
// CHECK17-NEXT: <end>
329+
330+
// CHECK18: <Kind>MultiStatement</Kind>
331+
// CHECK18-NEXT: <Content>case 1:
332+
// CHECK18-NEXT: return 0
333+
// CHECK18-NEXT: case 2:
334+
// CHECK18-NEXT: return 1</Content>
335+
// CHECK18-NEXT: <Type>Void</Type>
336+
// CHECK18-NEXT: <Context>swift_ide_test.(file).func decl</Context>
337+
// CHECK18-NEXT: <Entry>Multi</Entry>
338+
// CHECK18-NEXT: <ASTNodes>2</ASTNodes>
339+
// CHECK18-NEXT: <end>
340+
341+
// CHECK19: <Kind>SingleStatement</Kind>
342+
// CHECK19-NEXT: <Content>case 1:
343+
// CHECK19-NEXT: return 0</Content>
344+
// CHECK19-NEXT: <Type>Void</Type>
345+
// CHECK19-NEXT: <Context>swift_ide_test.(file).func decl</Context>
346+
// CHECK19-NEXT: <ASTNodes>1</ASTNodes>
347+
// CHECK19-NEXT: <end>
348+
349+
// CHECK20: <Kind>MultiStatement</Kind>
350+
// CHECK20-NEXT: <Content>case 2:
351+
// CHECK20-NEXT: return 1
352+
// CHECK20-NEXT: default:
353+
// CHECK20-NEXT: return a</Content>
354+
// CHECK20-NEXT: <Type>Void</Type>
355+
// CHECK20-NEXT: <Context>swift_ide_test.(file).func decl</Context>
356+
// CHECK20-NEXT: <Entry>Multi</Entry>
357+
// CHECK20-NEXT: <ASTNodes>2</ASTNodes>
358+
// CHECK20-NEXT: <end>

0 commit comments

Comments
 (0)