void parseSourceAndCreateLocatorForSelection(const std::string& source, LocationRange selection) { function.reset(new test::ParsedFunction(source)); locator.reset(new DefaultStatementLocator( [&](clang::SourceManager& sm, clang::Stmt& s) { return getStmtRange(sm, s); }, selection)); }
TEST_F(DefaultStatementLocatorTest, should_return_the_most_nested_statement) { parseSourceAndCreateLocatorForSelection( "void f() {\ntry {\nif (true) { int a; } else { int b; }\n} catch(...) { } }", { rowCol(2, 12), rowCol(2, 18) }); expectGetRangeForStmtAndReturn(0, { rowCol(1, 0), rowCol(3, 16) }); // try auto& sourceManager = function->getDecl()->getASTContext().getSourceManager(); auto ifStmt = *clang::dyn_cast<clang::CXXTryStmt>(nthStmt(0))->getTryBlock()->body_begin(); EXPECT_CALL(*this, getStmtRange(Ref(sourceManager), Ref(*ifStmt))) .WillRepeatedly(Return(LocationRange(rowCol(2, 0), rowCol(2, 37)))); auto intDecl = *clang::dyn_cast<clang::IfStmt>(ifStmt)->getThen()->child_begin(); EXPECT_CALL(*this, getStmtRange(Ref(sourceManager), Ref(*intDecl))) .WillRepeatedly(Return(LocationRange(rowCol(2, 12), rowCol(2, 18)))); auto stmts = locator->findStatementsInFunction(*function->getDecl()); ASSERT_EQ(1u, std::distance(begin(stmts), end(stmts))); ASSERT_TRUE(*stmts == intDecl); }
TEST_F(DefaultStatementLocatorTest, should_return_the_nested_statement_from_a_try_block) { parseSourceAndCreateLocatorForSelection( "void f() {\ntry { int a; } catch(...) { } }", { rowCol(1, 6), rowCol(1, 13) }); expectGetRangeForStmtAndReturn(0, { rowCol(1, 0), rowCol(1, 15) }); auto& sourceManager = function->getDecl()->getASTContext().getSourceManager(); auto intDecl = *clang::dyn_cast<clang::CXXTryStmt>(nthStmt(0))->getTryBlock()->body_begin(); EXPECT_CALL(*this, getStmtRange(Ref(sourceManager), Ref(*intDecl))) .WillRepeatedly(Return(LocationRange(rowCol(1, 6), rowCol(1, 13)))); auto stmts = locator->findStatementsInFunction(*function->getDecl()); ASSERT_EQ(1u, std::distance(begin(stmts), end(stmts))); ASSERT_TRUE(*stmts == intDecl); }
void expectGetRangeForStmtAndReturn(int index, LocationRange range) { auto& sourceManager = function->getDecl()->getASTContext().getSourceManager(); EXPECT_CALL(*this, getStmtRange(Ref(sourceManager), Ref(*nthStmt(index)))) .WillRepeatedly(Return(range)); }
TEST_F(findStatementsInFunctionOverlappingSelectionTest, should_return_an_empty_range_when_no_statement_overlaps_the_selection) { LocationRange selection{ rowCol(0, 1), rowCol(0, 3) }; parseFunctionWithStmts("\n int a;\nint b;"); const auto INT_A = 0, INT_B = 1; expectGetRangeForStmtNoAndReturn(INT_A, { rowCol(1, 2), rowCol(1, 8) }); expectGetRangeForStmtNoAndReturn(INT_B, { rowCol(2, 0), rowCol(2, 6) }); auto stmts = findStatementsInFunctionOverlappingSelection( *parsedFunctionDecl, selection, [&](clang::SourceManager& sm, clang::Stmt& s) { return getStmtRange(sm, s); }); ASSERT_TRUE(stmts.empty()); }
TEST_F(findStatementsInFunctionOverlappingSelectionTest, should_return_statements_overlapping_the_selection) { LocationRange selection{ rowCol(2, 0), rowCol(3, 4)}; parseFunctionWithStmts("\n int x;\n int y;\n int z;\n int w;\n"); const auto INT_X = 0, INT_Y = 1, INT_Z = 2, INT_W = 3; expectGetRangeForStmtNoAndReturn(INT_X, { rowCol(1, 2), rowCol(1, 8) }); expectGetRangeForStmtNoAndReturn(INT_Y, { rowCol(2, 2), rowCol(2, 8) }); expectGetRangeForStmtNoAndReturn(INT_Z, { rowCol(3, 2), rowCol(3, 8) }); expectGetRangeForStmtNoAndReturn(INT_W, { rowCol(4, 2), rowCol(4, 8) }); auto stmts = findStatementsInFunctionOverlappingSelection( *parsedFunctionDecl, selection, [&](clang::SourceManager& sm, clang::Stmt& s) { return getStmtRange(sm, s); }); expectRangeIs(stmts, { stmtNo(INT_Y), stmtNo(INT_Z) }); }
TEST_F(findStatementsInFunctionOverlappingSelectionTest, should_return_an_empty_range_for_an_empty_function) { LocationRange selection{rowCol(1, 1), rowCol(1, 1)}; parseFunctionWithStmts(" "); auto stmts = findStatementsInFunctionOverlappingSelection( *parsedFunctionDecl, selection, [&](clang::SourceManager& sm, clang::Stmt& s) { return getStmtRange(sm, s); }); ASSERT_TRUE(stmts.empty()); }
void expectGetRangeForStmtNoAndReturn(int index, LocationRange range) { auto& sourceManager = parsedFunctionDecl->getASTContext().getSourceManager(); EXPECT_CALL(*this, getStmtRange(Ref(sourceManager), Ref(*stmtNo(index)))) .WillRepeatedly(Return(range)); }