1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084 |
- //===- unittest/Tooling/ASTSelectionTest.cpp ------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "TestVisitor.h"
- #include "clang/Basic/SourceManager.h"
- #include "clang/Tooling/Refactoring/ASTSelection.h"
- using namespace clang;
- using namespace tooling;
- namespace {
- struct FileLocation {
- unsigned Line, Column;
- SourceLocation translate(const SourceManager &SM) {
- return SM.translateLineCol(SM.getMainFileID(), Line, Column);
- }
- };
- using FileRange = std::pair<FileLocation, FileLocation>;
- class SelectionFinderVisitor : public TestVisitor<SelectionFinderVisitor> {
- FileLocation Location;
- Optional<FileRange> SelectionRange;
- llvm::function_ref<void(SourceRange SelectionRange,
- Optional<SelectedASTNode>)>
- Consumer;
- public:
- SelectionFinderVisitor(FileLocation Location,
- Optional<FileRange> SelectionRange,
- llvm::function_ref<void(SourceRange SelectionRange,
- Optional<SelectedASTNode>)>
- Consumer)
- : Location(Location), SelectionRange(SelectionRange), Consumer(Consumer) {
- }
- bool VisitTranslationUnitDecl(const TranslationUnitDecl *TU) {
- const ASTContext &Context = TU->getASTContext();
- const SourceManager &SM = Context.getSourceManager();
- SourceRange SelRange;
- if (SelectionRange) {
- SelRange = SourceRange(SelectionRange->first.translate(SM),
- SelectionRange->second.translate(SM));
- } else {
- SourceLocation Loc = Location.translate(SM);
- SelRange = SourceRange(Loc, Loc);
- }
- Consumer(SelRange, findSelectedASTNodes(Context, SelRange));
- return false;
- }
- };
- /// This is a test utility function that computes the AST selection at the
- /// given location with an optional selection range.
- ///
- /// A location roughly corresponds to a cursor location in an editor, while
- /// the optional range corresponds to the selection range in an editor.
- void findSelectedASTNodesWithRange(
- StringRef Source, FileLocation Location, Optional<FileRange> SelectionRange,
- llvm::function_ref<void(SourceRange SelectionRange,
- Optional<SelectedASTNode>)>
- Consumer,
- SelectionFinderVisitor::Language Language =
- SelectionFinderVisitor::Lang_CXX11) {
- SelectionFinderVisitor Visitor(Location, SelectionRange, Consumer);
- EXPECT_TRUE(Visitor.runOver(Source, Language));
- }
- void findSelectedASTNodes(
- StringRef Source, FileLocation Location, Optional<FileRange> SelectionRange,
- llvm::function_ref<void(Optional<SelectedASTNode>)> Consumer,
- SelectionFinderVisitor::Language Language =
- SelectionFinderVisitor::Lang_CXX11) {
- findSelectedASTNodesWithRange(
- Source, Location, SelectionRange,
- [&](SourceRange, Optional<SelectedASTNode> Selection) {
- Consumer(std::move(Selection));
- },
- Language);
- }
- void checkNodeImpl(bool IsTypeMatched, const SelectedASTNode &Node,
- SourceSelectionKind SelectionKind, unsigned NumChildren) {
- ASSERT_TRUE(IsTypeMatched);
- EXPECT_EQ(Node.Children.size(), NumChildren);
- ASSERT_EQ(Node.SelectionKind, SelectionKind);
- }
- void checkDeclName(const SelectedASTNode &Node, StringRef Name) {
- const auto *ND = Node.Node.get<NamedDecl>();
- EXPECT_TRUE(!!ND);
- ASSERT_EQ(ND->getName(), Name);
- }
- template <typename T>
- const SelectedASTNode &
- checkNode(const SelectedASTNode &StmtNode, SourceSelectionKind SelectionKind,
- unsigned NumChildren = 0,
- typename std::enable_if<std::is_base_of<Stmt, T>::value, T>::type
- *StmtOverloadChecker = nullptr) {
- checkNodeImpl(isa<T>(StmtNode.Node.get<Stmt>()), StmtNode, SelectionKind,
- NumChildren);
- return StmtNode;
- }
- template <typename T>
- const SelectedASTNode &
- checkNode(const SelectedASTNode &DeclNode, SourceSelectionKind SelectionKind,
- unsigned NumChildren = 0, StringRef Name = "",
- typename std::enable_if<std::is_base_of<Decl, T>::value, T>::type
- *DeclOverloadChecker = nullptr) {
- checkNodeImpl(isa<T>(DeclNode.Node.get<Decl>()), DeclNode, SelectionKind,
- NumChildren);
- if (!Name.empty())
- checkDeclName(DeclNode, Name);
- return DeclNode;
- }
- struct ForAllChildrenOf {
- const SelectedASTNode &Node;
- static void childKindVerifier(const SelectedASTNode &Node,
- SourceSelectionKind SelectionKind) {
- for (const SelectedASTNode &Child : Node.Children) {
- ASSERT_EQ(Node.SelectionKind, SelectionKind);
- childKindVerifier(Child, SelectionKind);
- }
- }
- public:
- ForAllChildrenOf(const SelectedASTNode &Node) : Node(Node) {}
- void shouldHaveSelectionKind(SourceSelectionKind Kind) {
- childKindVerifier(Node, Kind);
- }
- };
- ForAllChildrenOf allChildrenOf(const SelectedASTNode &Node) {
- return ForAllChildrenOf(Node);
- }
- TEST(ASTSelectionFinder, CursorNoSelection) {
- findSelectedASTNodes(
- " void f() { }", {1, 1}, None,
- [](Optional<SelectedASTNode> Node) { EXPECT_FALSE(Node); });
- }
- TEST(ASTSelectionFinder, CursorAtStartOfFunction) {
- findSelectedASTNodes(
- "void f() { }", {1, 1}, None, [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- checkNode<TranslationUnitDecl>(*Node, SourceSelectionKind::None,
- /*NumChildren=*/1);
- checkNode<FunctionDecl>(Node->Children[0],
- SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/0, /*Name=*/"f");
- // Check that the dumping works.
- std::string DumpValue;
- llvm::raw_string_ostream OS(DumpValue);
- Node->Children[0].dump(OS);
- ASSERT_EQ(OS.str(), "FunctionDecl \"f\" contains-selection\n");
- });
- }
- TEST(ASTSelectionFinder, RangeNoSelection) {
- findSelectedASTNodes(
- " void f() { }", {1, 1}, FileRange{{1, 1}, {1, 1}},
- [](Optional<SelectedASTNode> Node) { EXPECT_FALSE(Node); });
- findSelectedASTNodes(
- " void f() { }", {1, 1}, FileRange{{1, 1}, {1, 2}},
- [](Optional<SelectedASTNode> Node) { EXPECT_FALSE(Node); });
- }
- TEST(ASTSelectionFinder, EmptyRangeFallbackToCursor) {
- findSelectedASTNodes("void f() { }", {1, 1}, FileRange{{1, 1}, {1, 1}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- checkNode<FunctionDecl>(
- Node->Children[0],
- SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/0, /*Name=*/"f");
- });
- }
- TEST(ASTSelectionFinder, WholeFunctionSelection) {
- StringRef Source = "int f(int x) { return x;\n}\nvoid f2() { }";
- // From 'int' until just after '}':
- findSelectedASTNodes(
- Source, {1, 1}, FileRange{{1, 1}, {2, 2}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Fn = checkNode<FunctionDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/2, /*Name=*/"f");
- checkNode<ParmVarDecl>(Fn.Children[0],
- SourceSelectionKind::InsideSelection);
- const auto &Body = checkNode<CompoundStmt>(
- Fn.Children[1], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- const auto &Return = checkNode<ReturnStmt>(
- Body.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- checkNode<ImplicitCastExpr>(Return.Children[0],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- checkNode<DeclRefExpr>(Return.Children[0].Children[0],
- SourceSelectionKind::InsideSelection);
- });
- // From 'int' until just before '}':
- findSelectedASTNodes(
- Source, {2, 1}, FileRange{{1, 1}, {2, 1}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Fn = checkNode<FunctionDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/2, /*Name=*/"f");
- const auto &Body = checkNode<CompoundStmt>(
- Fn.Children[1], SourceSelectionKind::ContainsSelectionEnd,
- /*NumChildren=*/1);
- checkNode<ReturnStmt>(Body.Children[0],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- });
- // From '{' until just after '}':
- findSelectedASTNodes(
- Source, {1, 14}, FileRange{{1, 14}, {2, 2}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Fn = checkNode<FunctionDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"f");
- const auto &Body = checkNode<CompoundStmt>(
- Fn.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1);
- checkNode<ReturnStmt>(Body.Children[0],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- });
- // From 'x' until just after '}':
- findSelectedASTNodes(
- Source, {2, 2}, FileRange{{1, 11}, {2, 2}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Fn = checkNode<FunctionDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/2, /*Name=*/"f");
- checkNode<ParmVarDecl>(Fn.Children[0],
- SourceSelectionKind::ContainsSelectionStart);
- const auto &Body = checkNode<CompoundStmt>(
- Fn.Children[1], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- checkNode<ReturnStmt>(Body.Children[0],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- });
- }
- TEST(ASTSelectionFinder, MultipleFunctionSelection) {
- StringRef Source = R"(void f0() {
- }
- void f1() { }
- void f2() { }
- void f3() { }
- )";
- auto SelectedF1F2 = [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 2u);
- checkNode<FunctionDecl>(Node->Children[0],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1, /*Name=*/"f1");
- checkNode<FunctionDecl>(Node->Children[1],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1, /*Name=*/"f2");
- };
- // Just after '}' of f0 and just before 'void' of f3:
- findSelectedASTNodes(Source, {2, 2}, FileRange{{2, 2}, {5, 1}}, SelectedF1F2);
- // Just before 'void' of f1 and just after '}' of f2:
- findSelectedASTNodes(Source, {3, 1}, FileRange{{3, 1}, {4, 14}},
- SelectedF1F2);
- }
- TEST(ASTSelectionFinder, MultipleStatementSelection) {
- StringRef Source = R"(void f(int x, int y) {
- int z = x;
- f(2, 3);
- if (x == 0) {
- return;
- }
- x = 1;
- return;
- })";
- // From 'f(2,3)' until just before 'x = 1;':
- findSelectedASTNodes(
- Source, {3, 2}, FileRange{{3, 2}, {7, 1}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Fn = checkNode<FunctionDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"f");
- const auto &Body = checkNode<CompoundStmt>(
- Fn.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/2);
- allChildrenOf(checkNode<CallExpr>(Body.Children[0],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/3))
- .shouldHaveSelectionKind(SourceSelectionKind::InsideSelection);
- allChildrenOf(checkNode<IfStmt>(Body.Children[1],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/2))
- .shouldHaveSelectionKind(SourceSelectionKind::InsideSelection);
- });
- // From 'f(2,3)' until just before ';' in 'x = 1;':
- findSelectedASTNodes(
- Source, {3, 2}, FileRange{{3, 2}, {7, 8}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Fn = checkNode<FunctionDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"f");
- const auto &Body = checkNode<CompoundStmt>(
- Fn.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/3);
- checkNode<CallExpr>(Body.Children[0],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/3);
- checkNode<IfStmt>(Body.Children[1],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/2);
- checkNode<BinaryOperator>(Body.Children[2],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/2);
- });
- // From the middle of 'int z = 3' until the middle of 'x = 1;':
- findSelectedASTNodes(
- Source, {2, 10}, FileRange{{2, 10}, {7, 5}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Fn = checkNode<FunctionDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"f");
- const auto &Body = checkNode<CompoundStmt>(
- Fn.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/4);
- checkNode<DeclStmt>(Body.Children[0],
- SourceSelectionKind::ContainsSelectionStart,
- /*NumChildren=*/1);
- checkNode<CallExpr>(Body.Children[1],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/3);
- checkNode<IfStmt>(Body.Children[2],
- SourceSelectionKind::InsideSelection,
- /*NumChildren=*/2);
- checkNode<BinaryOperator>(Body.Children[3],
- SourceSelectionKind::ContainsSelectionEnd,
- /*NumChildren=*/1);
- });
- }
- TEST(ASTSelectionFinder, SelectionInFunctionInObjCImplementation) {
- StringRef Source = R"(
- @interface I
- @end
- @implementation I
- int notSelected() { }
- int selected(int x) {
- return x;
- }
- @end
- @implementation I(Cat)
- void catF() { }
- @end
- void outerFunction() { }
- )";
- // Just the 'x' expression in 'selected':
- findSelectedASTNodes(
- Source, {9, 10}, FileRange{{9, 10}, {9, 11}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Impl = checkNode<ObjCImplementationDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"I");
- const auto &Fn = checkNode<FunctionDecl>(
- Impl.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"selected");
- allChildrenOf(Fn).shouldHaveSelectionKind(
- SourceSelectionKind::ContainsSelection);
- },
- SelectionFinderVisitor::Lang_OBJC);
- // The entire 'catF':
- findSelectedASTNodes(
- Source, {15, 1}, FileRange{{15, 1}, {15, 16}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Impl = checkNode<ObjCCategoryImplDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"Cat");
- const auto &Fn = checkNode<FunctionDecl>(
- Impl.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"catF");
- allChildrenOf(Fn).shouldHaveSelectionKind(
- SourceSelectionKind::ContainsSelection);
- },
- SelectionFinderVisitor::Lang_OBJC);
- // From the line before 'selected' to the line after 'catF':
- findSelectedASTNodes(
- Source, {16, 1}, FileRange{{7, 1}, {16, 1}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 2u);
- const auto &Impl = checkNode<ObjCImplementationDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelectionStart,
- /*NumChildren=*/1, /*Name=*/"I");
- const auto &Selected = checkNode<FunctionDecl>(
- Impl.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/2, /*Name=*/"selected");
- allChildrenOf(Selected).shouldHaveSelectionKind(
- SourceSelectionKind::InsideSelection);
- const auto &Cat = checkNode<ObjCCategoryImplDecl>(
- Node->Children[1], SourceSelectionKind::ContainsSelectionEnd,
- /*NumChildren=*/1, /*Name=*/"Cat");
- const auto &CatF = checkNode<FunctionDecl>(
- Cat.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1, /*Name=*/"catF");
- allChildrenOf(CatF).shouldHaveSelectionKind(
- SourceSelectionKind::InsideSelection);
- },
- SelectionFinderVisitor::Lang_OBJC);
- // Just the 'outer' function:
- findSelectedASTNodes(Source, {19, 1}, FileRange{{19, 1}, {19, 25}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- checkNode<FunctionDecl>(
- Node->Children[0],
- SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"outerFunction");
- },
- SelectionFinderVisitor::Lang_OBJC);
- }
- TEST(ASTSelectionFinder, FunctionInObjCImplementationCarefulWithEarlyExit) {
- StringRef Source = R"(
- @interface I
- @end
- @implementation I
- void selected() {
- }
- - (void) method { }
- @end
- )";
- // Just 'selected'
- findSelectedASTNodes(
- Source, {6, 1}, FileRange{{6, 1}, {7, 2}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Impl = checkNode<ObjCImplementationDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"I");
- checkNode<FunctionDecl>(Impl.Children[0],
- SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, /*Name=*/"selected");
- },
- SelectionFinderVisitor::Lang_OBJC);
- }
- TEST(ASTSelectionFinder, AvoidImplicitDeclarations) {
- StringRef Source = R"(
- struct Copy {
- int x;
- };
- void foo() {
- Copy x;
- Copy y = x;
- }
- )";
- // The entire struct 'Copy':
- findSelectedASTNodes(
- Source, {2, 1}, FileRange{{2, 1}, {4, 3}},
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Record = checkNode<CXXRecordDecl>(
- Node->Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1, /*Name=*/"Copy");
- checkNode<FieldDecl>(Record.Children[0],
- SourceSelectionKind::InsideSelection);
- });
- }
- TEST(ASTSelectionFinder, CorrectEndForObjectiveCImplementation) {
- StringRef Source = R"(
- @interface I
- @end
- @implementation I
- @ end
- )";
- // Just after '@ end'
- findSelectedASTNodes(Source, {5, 6}, None,
- [](Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- checkNode<ObjCImplementationDecl>(
- Node->Children[0],
- SourceSelectionKind::ContainsSelection);
- },
- SelectionFinderVisitor::Lang_OBJC);
- }
- const SelectedASTNode &checkFnBody(const Optional<SelectedASTNode> &Node,
- StringRef Name) {
- EXPECT_TRUE(Node);
- EXPECT_EQ(Node->Children.size(), 1u);
- const auto &Fn = checkNode<FunctionDecl>(
- Node->Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1, Name);
- return checkNode<CompoundStmt>(Fn.Children[0],
- SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1);
- }
- TEST(ASTSelectionFinder, SelectObjectiveCPseudoObjectExprs) {
- StringRef Source = R"(
- @interface I
- @property(readwrite) int prop;
- @end
- void selectProp(I *i) {
- (void)i.prop;
- i.prop = 21;
- }
- @interface NSMutableArray
- - (id)objectAtIndexedSubscript:(unsigned int)index;
- - (void)setObject:(id)object atIndexedSubscript:(unsigned int)index;
- @end
- void selectSubscript(NSMutableArray *array, I *i) {
- (void)array[10];
- array[i.prop] = i;
- }
- )";
- // Just 'i.prop'.
- findSelectedASTNodes(
- Source, {6, 7}, FileRange{{6, 7}, {6, 13}},
- [](Optional<SelectedASTNode> Node) {
- const auto &CS = checkFnBody(Node, /*Name=*/"selectProp");
- const auto &CCast = checkNode<CStyleCastExpr>(
- CS.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1);
- const auto &POE = checkNode<PseudoObjectExpr>(
- CCast.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1);
- const auto &PRE = checkNode<ObjCPropertyRefExpr>(
- POE.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1);
- const auto &Cast = checkNode<ImplicitCastExpr>(
- PRE.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- checkNode<DeclRefExpr>(Cast.Children[0],
- SourceSelectionKind::InsideSelection);
- },
- SelectionFinderVisitor::Lang_OBJC);
- // Just 'i.prop = 21'
- findSelectedASTNodes(
- Source, {7, 1}, FileRange{{7, 1}, {7, 12}},
- [](Optional<SelectedASTNode> Node) {
- const auto &CS = checkFnBody(Node, /*Name=*/"selectProp");
- const auto &POE = checkNode<PseudoObjectExpr>(
- CS.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1);
- const auto &BinOp = checkNode<BinaryOperator>(
- POE.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/2);
- const auto &PRE = checkNode<ObjCPropertyRefExpr>(
- BinOp.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- const auto &Cast = checkNode<ImplicitCastExpr>(
- PRE.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- checkNode<DeclRefExpr>(Cast.Children[0],
- SourceSelectionKind::InsideSelection);
- checkNode<IntegerLiteral>(BinOp.Children[1],
- SourceSelectionKind::InsideSelection);
- },
- SelectionFinderVisitor::Lang_OBJC);
- // Just 'array[10]'
- findSelectedASTNodes(
- Source, {17, 9}, FileRange{{17, 9}, {17, 18}},
- [](Optional<SelectedASTNode> Node) {
- const auto &CS = checkFnBody(Node, /*Name=*/"selectSubscript");
- const auto &CCast = checkNode<CStyleCastExpr>(
- CS.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1);
- const auto &POE = checkNode<PseudoObjectExpr>(
- CCast.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1);
- const auto &SRE = checkNode<ObjCSubscriptRefExpr>(
- POE.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/2);
- const auto &Cast = checkNode<ImplicitCastExpr>(
- SRE.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- checkNode<DeclRefExpr>(Cast.Children[0],
- SourceSelectionKind::InsideSelection);
- checkNode<IntegerLiteral>(SRE.Children[1],
- SourceSelectionKind::InsideSelection);
- },
- SelectionFinderVisitor::Lang_OBJC);
- // Just 'array[i.prop] = array'
- findSelectedASTNodes(
- Source, {18, 3}, FileRange{{18, 3}, {18, 20}},
- [](Optional<SelectedASTNode> Node) {
- const auto &CS = checkFnBody(Node, /*Name=*/"selectSubscript");
- const auto &POE = checkNode<PseudoObjectExpr>(
- CS.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/1);
- const auto &BinOp = checkNode<BinaryOperator>(
- POE.Children[0], SourceSelectionKind::ContainsSelection,
- /*NumChildren=*/2);
- const auto &SRE = checkNode<ObjCSubscriptRefExpr>(
- BinOp.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/2);
- const auto &Cast = checkNode<ImplicitCastExpr>(
- SRE.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- checkNode<DeclRefExpr>(Cast.Children[0],
- SourceSelectionKind::InsideSelection);
- const auto &POE2 = checkNode<PseudoObjectExpr>(
- SRE.Children[1], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- const auto &PRE = checkNode<ObjCPropertyRefExpr>(
- POE2.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- const auto &Cast2 = checkNode<ImplicitCastExpr>(
- PRE.Children[0], SourceSelectionKind::InsideSelection,
- /*NumChildren=*/1);
- checkNode<DeclRefExpr>(Cast2.Children[0],
- SourceSelectionKind::InsideSelection);
- checkNode<DeclRefExpr>(BinOp.Children[1],
- SourceSelectionKind::InsideSelection);
- },
- SelectionFinderVisitor::Lang_OBJC);
- }
- TEST(ASTSelectionFinder, SimpleCodeRangeASTSelection) {
- StringRef Source = R"(void f(int x, int y) {
- int z = x;
- f(2, 3);
- if (x == 0) {
- return;
- }
- x = 1;
- return;
- }
- void f2() {
- int m = 0;
- }
- )";
- // No selection range.
- findSelectedASTNodesWithRange(
- Source, {2, 2}, None,
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_FALSE(SelectedCode);
- });
- findSelectedASTNodesWithRange(
- Source, {2, 2}, FileRange{{2, 2}, {2, 2}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_FALSE(SelectedCode);
- });
- // Range that spans multiple functions is an invalid code range.
- findSelectedASTNodesWithRange(
- Source, {2, 2}, FileRange{{7, 2}, {12, 1}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_FALSE(SelectedCode);
- });
- // Just 'z = x;':
- findSelectedASTNodesWithRange(
- Source, {2, 2}, FileRange{{2, 2}, {2, 13}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<DeclStmt>((*SelectedCode)[0]));
- ArrayRef<SelectedASTNode::ReferenceType> Parents =
- SelectedCode->getParents();
- EXPECT_EQ(Parents.size(), 3u);
- EXPECT_TRUE(
- isa<TranslationUnitDecl>(Parents[0].get().Node.get<Decl>()));
- // Function 'f' definition.
- EXPECT_TRUE(isa<FunctionDecl>(Parents[1].get().Node.get<Decl>()));
- // Function body of function 'F'.
- EXPECT_TRUE(isa<CompoundStmt>(Parents[2].get().Node.get<Stmt>()));
- });
- // From 'f(2,3)' until just before 'x = 1;':
- findSelectedASTNodesWithRange(
- Source, {3, 2}, FileRange{{3, 2}, {7, 1}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 2u);
- EXPECT_TRUE(isa<CallExpr>((*SelectedCode)[0]));
- EXPECT_TRUE(isa<IfStmt>((*SelectedCode)[1]));
- ArrayRef<SelectedASTNode::ReferenceType> Parents =
- SelectedCode->getParents();
- EXPECT_EQ(Parents.size(), 3u);
- EXPECT_TRUE(
- isa<TranslationUnitDecl>(Parents[0].get().Node.get<Decl>()));
- // Function 'f' definition.
- EXPECT_TRUE(isa<FunctionDecl>(Parents[1].get().Node.get<Decl>()));
- // Function body of function 'F'.
- EXPECT_TRUE(isa<CompoundStmt>(Parents[2].get().Node.get<Stmt>()));
- });
- // From 'f(2,3)' until just before ';' in 'x = 1;':
- findSelectedASTNodesWithRange(
- Source, {3, 2}, FileRange{{3, 2}, {7, 8}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 3u);
- EXPECT_TRUE(isa<CallExpr>((*SelectedCode)[0]));
- EXPECT_TRUE(isa<IfStmt>((*SelectedCode)[1]));
- EXPECT_TRUE(isa<BinaryOperator>((*SelectedCode)[2]));
- });
- // From the middle of 'int z = 3' until the middle of 'x = 1;':
- findSelectedASTNodesWithRange(
- Source, {2, 10}, FileRange{{2, 10}, {7, 5}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 4u);
- EXPECT_TRUE(isa<DeclStmt>((*SelectedCode)[0]));
- EXPECT_TRUE(isa<CallExpr>((*SelectedCode)[1]));
- EXPECT_TRUE(isa<IfStmt>((*SelectedCode)[2]));
- EXPECT_TRUE(isa<BinaryOperator>((*SelectedCode)[3]));
- });
- }
- TEST(ASTSelectionFinder, OutOfBodyCodeRange) {
- StringRef Source = R"(
- int codeRange = 2 + 3;
- )";
- // '2+3' expression.
- findSelectedASTNodesWithRange(
- Source, {2, 17}, FileRange{{2, 17}, {2, 22}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<BinaryOperator>((*SelectedCode)[0]));
- ArrayRef<SelectedASTNode::ReferenceType> Parents =
- SelectedCode->getParents();
- EXPECT_EQ(Parents.size(), 2u);
- EXPECT_TRUE(
- isa<TranslationUnitDecl>(Parents[0].get().Node.get<Decl>()));
- // Variable 'codeRange'.
- EXPECT_TRUE(isa<VarDecl>(Parents[1].get().Node.get<Decl>()));
- });
- }
- TEST(ASTSelectionFinder, SelectVarDeclStmt) {
- StringRef Source = R"(
- void f() {
- {
- int a;
- }
- }
- )";
- // 'int a'
- findSelectedASTNodesWithRange(
- Source, {4, 8}, FileRange{{4, 8}, {4, 14}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<DeclStmt>((*SelectedCode)[0]));
- ArrayRef<SelectedASTNode::ReferenceType> Parents =
- SelectedCode->getParents();
- EXPECT_EQ(Parents.size(), 4u);
- EXPECT_TRUE(
- isa<TranslationUnitDecl>(Parents[0].get().Node.get<Decl>()));
- // Function 'f' definition.
- EXPECT_TRUE(isa<FunctionDecl>(Parents[1].get().Node.get<Decl>()));
- // Function body of function 'F'.
- EXPECT_TRUE(isa<CompoundStmt>(Parents[2].get().Node.get<Stmt>()));
- // Compound statement in body of 'F'.
- EXPECT_TRUE(isa<CompoundStmt>(Parents[3].get().Node.get<Stmt>()));
- });
- }
- TEST(ASTSelectionFinder, SelectEntireDeclStmtRange) {
- StringRef Source = R"(
- void f(int x, int y) {
- int a = x * y;
- }
- )";
- // 'int a = x * y'
- findSelectedASTNodesWithRange(
- Source, {3, 4}, FileRange{{3, 4}, {3, 17}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<DeclStmt>((*SelectedCode)[0]));
- ArrayRef<SelectedASTNode::ReferenceType> Parents =
- SelectedCode->getParents();
- EXPECT_EQ(Parents.size(), 3u);
- EXPECT_TRUE(
- isa<TranslationUnitDecl>(Parents[0].get().Node.get<Decl>()));
- // Function 'f' definition.
- EXPECT_TRUE(isa<FunctionDecl>(Parents[1].get().Node.get<Decl>()));
- // Function body of function 'F'.
- EXPECT_TRUE(isa<CompoundStmt>(Parents[2].get().Node.get<Stmt>()));
- });
- }
- TEST(ASTSelectionFinder, SelectEntireDeclStmtRangeWithMultipleDecls) {
- StringRef Source = R"(
- void f(int x, int y) {
- int a = x * y, b = x - y;
- }
- )";
- // 'b = x - y'
- findSelectedASTNodesWithRange(
- Source, {3, 19}, FileRange{{3, 19}, {3, 28}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<DeclStmt>((*SelectedCode)[0]));
- ArrayRef<SelectedASTNode::ReferenceType> Parents =
- SelectedCode->getParents();
- EXPECT_EQ(Parents.size(), 3u);
- EXPECT_TRUE(
- isa<TranslationUnitDecl>(Parents[0].get().Node.get<Decl>()));
- // Function 'f' definition.
- EXPECT_TRUE(isa<FunctionDecl>(Parents[1].get().Node.get<Decl>()));
- // Function body of function 'F'.
- EXPECT_TRUE(isa<CompoundStmt>(Parents[2].get().Node.get<Stmt>()));
- });
- }
- TEST(ASTSelectionFinder, SimpleCodeRangeASTSelectionInObjCMethod) {
- StringRef Source = R"(@interface I @end
- @implementation I
- - (void) f:(int)x with:(int) y {
- int z = x;
- [self f: 2 with: 3];
- if (x == 0) {
- return;
- }
- x = 1;
- return;
- }
- - (void)f2 {
- int m = 0;
- }
- @end
- )";
- // Range that spans multiple methods is an invalid code range.
- findSelectedASTNodesWithRange(
- Source, {9, 2}, FileRange{{9, 2}, {13, 1}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_FALSE(SelectedCode);
- },
- SelectionFinderVisitor::Lang_OBJC);
- // Just 'z = x;':
- findSelectedASTNodesWithRange(
- Source, {4, 2}, FileRange{{4, 2}, {4, 13}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<DeclStmt>((*SelectedCode)[0]));
- ArrayRef<SelectedASTNode::ReferenceType> Parents =
- SelectedCode->getParents();
- EXPECT_EQ(Parents.size(), 4u);
- EXPECT_TRUE(
- isa<TranslationUnitDecl>(Parents[0].get().Node.get<Decl>()));
- // 'I' @implementation.
- EXPECT_TRUE(isa<ObjCImplDecl>(Parents[1].get().Node.get<Decl>()));
- // Function 'f' definition.
- EXPECT_TRUE(isa<ObjCMethodDecl>(Parents[2].get().Node.get<Decl>()));
- // Function body of function 'F'.
- EXPECT_TRUE(isa<CompoundStmt>(Parents[3].get().Node.get<Stmt>()));
- },
- SelectionFinderVisitor::Lang_OBJC);
- // From '[self f: 2 with: 3]' until just before 'x = 1;':
- findSelectedASTNodesWithRange(
- Source, {5, 2}, FileRange{{5, 2}, {9, 1}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 2u);
- EXPECT_TRUE(isa<ObjCMessageExpr>((*SelectedCode)[0]));
- EXPECT_TRUE(isa<IfStmt>((*SelectedCode)[1]));
- ArrayRef<SelectedASTNode::ReferenceType> Parents =
- SelectedCode->getParents();
- EXPECT_EQ(Parents.size(), 4u);
- EXPECT_TRUE(
- isa<TranslationUnitDecl>(Parents[0].get().Node.get<Decl>()));
- // 'I' @implementation.
- EXPECT_TRUE(isa<ObjCImplDecl>(Parents[1].get().Node.get<Decl>()));
- // Function 'f' definition.
- EXPECT_TRUE(isa<ObjCMethodDecl>(Parents[2].get().Node.get<Decl>()));
- // Function body of function 'F'.
- EXPECT_TRUE(isa<CompoundStmt>(Parents[3].get().Node.get<Stmt>()));
- },
- SelectionFinderVisitor::Lang_OBJC);
- }
- TEST(ASTSelectionFinder, CanonicalizeObjCStringLiteral) {
- StringRef Source = R"(
- void foo() {
- (void)@"test";
- }
- )";
- // Just '"test"':
- findSelectedASTNodesWithRange(
- Source, {3, 10}, FileRange{{3, 10}, {3, 16}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<ObjCStringLiteral>((*SelectedCode)[0]));
- },
- SelectionFinderVisitor::Lang_OBJC);
- // Just 'test':
- findSelectedASTNodesWithRange(
- Source, {3, 11}, FileRange{{3, 11}, {3, 15}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<ObjCStringLiteral>((*SelectedCode)[0]));
- },
- SelectionFinderVisitor::Lang_OBJC);
- }
- TEST(ASTSelectionFinder, CanonicalizeMemberCalleeToCall) {
- StringRef Source = R"(
- class AClass { public:
- void method();
- int afield;
- void selectWholeCallWhenJustMethodSelected(int &i) {
- method();
- }
- };
- void selectWholeCallWhenJustMethodSelected() {
- AClass a;
- a.method();
- }
- void dontSelectArgument(AClass &a) {
- a.selectWholeCallWhenJustMethodSelected(a.afield);
- }
- )";
- // Just 'method' with implicit 'this':
- findSelectedASTNodesWithRange(
- Source, {6, 5}, FileRange{{6, 5}, {6, 11}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<CXXMemberCallExpr>((*SelectedCode)[0]));
- });
- // Just 'method':
- findSelectedASTNodesWithRange(
- Source, {11, 5}, FileRange{{11, 5}, {11, 11}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<CXXMemberCallExpr>((*SelectedCode)[0]));
- });
- // Just 'afield', which should not select the call.
- findSelectedASTNodesWithRange(
- Source, {14, 5}, FileRange{{14, 45}, {14, 51}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_FALSE(isa<CXXMemberCallExpr>((*SelectedCode)[0]));
- });
- }
- TEST(ASTSelectionFinder, CanonicalizeFuncCalleeToCall) {
- StringRef Source = R"(
- void function();
- void test() {
- function();
- }
- )";
- // Just 'function':
- findSelectedASTNodesWithRange(
- Source, {5, 3}, FileRange{{5, 3}, {5, 11}},
- [](SourceRange SelectionRange, Optional<SelectedASTNode> Node) {
- EXPECT_TRUE(Node);
- Node->dump();
- Optional<CodeRangeASTSelection> SelectedCode =
- CodeRangeASTSelection::create(SelectionRange, std::move(*Node));
- EXPECT_TRUE(SelectedCode);
- EXPECT_EQ(SelectedCode->size(), 1u);
- EXPECT_TRUE(isa<CallExpr>((*SelectedCode)[0]));
- EXPECT_TRUE(isa<CompoundStmt>(
- SelectedCode->getParents()[SelectedCode->getParents().size() - 1]
- .get()
- .Node.get<Stmt>()));
- });
- }
- } // end anonymous namespace
|