Skip to content

Commit f08601f

Browse files
authored
Merge pull request #5321 from mxswd/tuple-expr-sourcerange
Updated TupleExpr's getSourceRange to inspect child elements source ranges
2 parents 4c6f7e6 + 7f1f3b5 commit f08601f

File tree

2 files changed

+68
-15
lines changed

2 files changed

+68
-15
lines changed

lib/AST/Expr.cpp

+14-2
Original file line numberDiff line numberDiff line change
@@ -1322,14 +1322,26 @@ SourceRange TupleExpr::getSourceRange() const {
13221322
} else if (getNumElements() == 0) {
13231323
return { SourceLoc(), SourceLoc() };
13241324
} else {
1325-
start = getElement(0)->getStartLoc();
1325+
// Scan forward for the first valid source loc.
1326+
for (Expr *expr : getElements()) {
1327+
start = expr->getStartLoc();
1328+
if (start.isValid()) {
1329+
break;
1330+
}
1331+
}
13261332
}
13271333

13281334
if (hasTrailingClosure() || RParenLoc.isInvalid()) {
13291335
if (getNumElements() == 0) {
13301336
return { SourceLoc(), SourceLoc() };
13311337
} else {
1332-
end = getElements().back()->getEndLoc();
1338+
// Scan backwards for a valid source loc.
1339+
for (Expr *expr : reversed(getElements())) {
1340+
end = expr->getEndLoc();
1341+
if (end.isValid()) {
1342+
break;
1343+
}
1344+
}
13331345
}
13341346
} else {
13351347
end = RParenLoc;

unittests/AST/SourceLocTests.cpp

+54-13
Original file line numberDiff line numberDiff line change
@@ -199,22 +199,24 @@ TEST(SourceLoc, TupleExpr) {
199199
TestContext C;
200200

201201
// In a TupleExpr, if the parens are both invalid, then you can only have a
202-
// valid range iff both the first element and last element have valid ranges.
202+
// valid range if there exists at least one expr with a valid source range.
203+
// The tuple's source range will be the upper bound of the inner source
204+
// ranges.
203205
// Source ranges also have the property:
204206
// Start.isValid() == End.isValid()
205207
// For example, given the buffer "one", of the form:
206208
// (tuple_expr
207209
// (declref_expr range=[test.swift:1:0 - line:1:2] ...)
208210
// (declref_expr range=invalid ...))
209-
// the range of this TupleExpr is SourceLoc() (invalid).
211+
// the range of this TupleExpr is 1:0 - 1:2.
210212
// v invalid v invalid
211213
// ( one, two )
212214
// valid ^ invalid ^
213215
// COL: xxxxxx012xxxxxxxxxxxxxxxxx
214-
// but the SourceRange of 'one' is 1:0 - 1:2.
216+
// and the SourceRange of 'one' is 1:0 - 1:2.
215217

216-
// 012
217-
auto bufferID = C.Ctx.SourceMgr.addMemBufferCopy("one");
218+
// 01234567
219+
auto bufferID = C.Ctx.SourceMgr.addMemBufferCopy("one four");
218220
SourceLoc start = C.Ctx.SourceMgr.getLocForBufferStart(bufferID);
219221

220222
auto one = new (C.Ctx) UnresolvedDeclRefExpr(
@@ -227,22 +229,61 @@ TEST(SourceLoc, TupleExpr) {
227229
DeclRefKind::Ordinary,
228230
DeclNameLoc());
229231

232+
auto three = new (C.Ctx) UnresolvedDeclRefExpr(
233+
C.Ctx.getIdentifier("three"),
234+
DeclRefKind::Ordinary,
235+
DeclNameLoc());
236+
237+
auto four = new (C.Ctx) UnresolvedDeclRefExpr(
238+
C.Ctx.getIdentifier("four"),
239+
DeclRefKind::Ordinary,
240+
DeclNameLoc(start.getAdvancedLoc(4)));
241+
242+
EXPECT_EQ(start, one->getStartLoc());
243+
EXPECT_EQ(SourceLoc(), two->getStartLoc());
244+
245+
// a tuple with only invalid elements
246+
SmallVector<Expr *, 2> subExprsInvalid({ two, three });
247+
SmallVector<Identifier, 2> subExprNamesInvalid(2, Identifier());
248+
auto allInvalid = TupleExpr::createImplicit(C.Ctx, subExprsInvalid, subExprNamesInvalid);
249+
250+
EXPECT_EQ(SourceLoc(), allInvalid->getStartLoc());
251+
EXPECT_EQ(SourceLoc(), allInvalid->getEndLoc());
252+
EXPECT_EQ(SourceRange(), allInvalid->getSourceRange());
253+
230254
// the tuple from the example
231255
SmallVector<Expr *, 2> subExprsRight({ one, two });
232256
SmallVector<Identifier, 2> subExprNamesRight(2, Identifier());
233257
auto rightInvalidTuple = TupleExpr::createImplicit(C.Ctx, subExprsRight, subExprNamesRight);
234258

235-
EXPECT_EQ(start, one->getStartLoc());
236-
EXPECT_EQ(SourceLoc(), rightInvalidTuple->getStartLoc());
237-
EXPECT_EQ(SourceLoc(), rightInvalidTuple->getEndLoc());
238-
EXPECT_EQ(SourceRange(), rightInvalidTuple->getSourceRange());
259+
EXPECT_EQ(start, rightInvalidTuple->getStartLoc());
260+
EXPECT_EQ(start, rightInvalidTuple->getEndLoc());
261+
EXPECT_EQ(SourceRange(start, start), rightInvalidTuple->getSourceRange());
239262

240263
SmallVector<Expr *, 2> subExprsLeft({ two, one });
241264
SmallVector<Identifier, 2> subExprNamesLeft(2, Identifier());
242265
auto leftInvalidTuple = TupleExpr::createImplicit(C.Ctx, subExprsLeft, subExprNamesLeft);
243266

244-
EXPECT_EQ(start, one->getStartLoc());
245-
EXPECT_EQ(SourceLoc(), leftInvalidTuple->getStartLoc());
246-
EXPECT_EQ(SourceLoc(), leftInvalidTuple->getEndLoc());
247-
EXPECT_EQ(SourceRange(), leftInvalidTuple->getSourceRange());
267+
EXPECT_EQ(start, leftInvalidTuple->getStartLoc());
268+
EXPECT_EQ(start, leftInvalidTuple->getEndLoc());
269+
EXPECT_EQ(SourceRange(start, start), leftInvalidTuple->getSourceRange());
270+
271+
// Some TupleExprs are triples. If only the middle expr has a valid SourceLoc
272+
// then the TupleExpr's SourceLoc should point at that.
273+
SmallVector<Expr *, 3> subExprsTriple({ two, one, two });
274+
SmallVector<Identifier, 3> subExprNamesTriple(3, Identifier());
275+
auto tripleValidMid = TupleExpr::createImplicit(C.Ctx, subExprsTriple, subExprNamesTriple);
276+
EXPECT_EQ(start, tripleValidMid->getStartLoc());
277+
EXPECT_EQ(start, tripleValidMid->getEndLoc());
278+
EXPECT_EQ(SourceRange(start, start), tripleValidMid->getSourceRange());
279+
280+
// Some TupleExprs are quadruples. Quadruples should point at the range from
281+
// the first to the last valid exprs.
282+
SmallVector<Expr *, 4> subExprsQuad({ one, two, four, three });
283+
SmallVector<Identifier, 4> subExprNamesQuad(4, Identifier());
284+
auto quadValidMids = TupleExpr::createImplicit(C.Ctx, subExprsQuad, subExprNamesQuad);
285+
EXPECT_EQ(start, quadValidMids->getStartLoc());
286+
EXPECT_EQ(start.getAdvancedLoc(4), quadValidMids->getEndLoc());
287+
EXPECT_EQ(SourceRange(start, start.getAdvancedLoc(4)), quadValidMids->getSourceRange());
288+
248289
}

0 commit comments

Comments
 (0)