@@ -242,6 +242,7 @@ class ModelASTWalker : public ASTWalker {
242
242
const LangOptions &LangOpts;
243
243
const SourceManager &SM;
244
244
unsigned BufferID;
245
+ ASTContext &Ctx;
245
246
std::vector<StructureElement> SubStructureStack;
246
247
SourceLoc LastLoc;
247
248
static const std::regex &getURLRegex (StringRef Protocol);
@@ -262,6 +263,7 @@ class ModelASTWalker : public ASTWalker {
262
263
LangOpts (File.getASTContext().LangOpts),
263
264
SM(File.getASTContext().SourceMgr),
264
265
BufferID(File.getBufferID().getValue()),
266
+ Ctx(File.getASTContext()),
265
267
Walker(Walker) { }
266
268
267
269
void visitSourceFile (SourceFile &SrcFile, ArrayRef<SyntaxNode> Tokens);
@@ -513,13 +515,14 @@ std::pair<bool, Expr *> ModelASTWalker::walkToExprPre(Expr *E) {
513
515
SN.BodyRange = innerCharSourceRangeFromSourceRange (SM, E->getSourceRange ());
514
516
pushStructureNode (SN, E);
515
517
} else if (auto *Tup = dyn_cast<TupleExpr>(E)) {
518
+ auto *ParentE = Parent.getAsExpr ();
516
519
if (isCurrentCallArgExpr (Tup)) {
517
520
for (unsigned I = 0 ; I < Tup->getNumElements (); ++ I) {
518
521
SourceLoc NameLoc = Tup->getElementNameLoc (I);
519
522
if (NameLoc.isValid ())
520
523
passTokenNodesUntil (NameLoc, PassNodesBehavior::ExcludeNodeAtLocation);
521
524
}
522
- } else {
525
+ } else if (!ParentE || !isa<InterpolatedStringLiteralExpr>(ParentE)) {
523
526
SyntaxStructureNode SN;
524
527
SN.Kind = SyntaxStructureKind::TupleExpression;
525
528
SN.Range = charSourceRangeFromSourceRange (SM, Tup->getSourceRange ());
@@ -554,6 +557,18 @@ std::pair<bool, Expr *> ModelASTWalker::walkToExprPre(Expr *E) {
554
557
subExpr->walk (*this );
555
558
}
556
559
return { false , walkToExprPost (SE) };
560
+ } else if (auto *ISL = dyn_cast<InterpolatedStringLiteralExpr>(E)) {
561
+ // Don't visit the child expressions directly. Instead visit the arguments
562
+ // of each appendStringLiteral/appendInterpolation CallExpr so we don't
563
+ // try to output structure nodes for those calls.
564
+ llvm::SaveAndRestore<ASTWalker::ParentTy> SetParent (Parent, E);
565
+ ISL->forEachSegment (Ctx, [&](bool isInterpolation, CallExpr *CE) {
566
+ if (isInterpolation) {
567
+ if (auto *Arg = CE->getArg ())
568
+ Arg->walk (*this );
569
+ }
570
+ });
571
+ return { false , walkToExprPost (E) };
557
572
}
558
573
559
574
return { true , E };
0 commit comments