1 //===---- QueryParserTest.cpp - clang-query test --------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "QueryParser.h" 11 #include "Query.h" 12 #include "QuerySession.h" 13 #include "llvm/LineEditor/LineEditor.h" 14 #include "gtest/gtest.h" 15 16 using namespace clang; 17 using namespace clang::query; 18 19 class QueryParserTest : public ::testing::Test { 20 protected: 21 QueryParserTest() : QS(llvm::ArrayRef<std::unique_ptr<ASTUnit>>()) {} 22 QueryRef parse(StringRef Code) { return QueryParser::parse(Code, QS); } 23 24 QuerySession QS; 25 }; 26 27 TEST_F(QueryParserTest, NoOp) { 28 QueryRef Q = parse(""); 29 EXPECT_TRUE(isa<NoOpQuery>(Q)); 30 31 Q = parse("\n"); 32 EXPECT_TRUE(isa<NoOpQuery>(Q)); 33 } 34 35 TEST_F(QueryParserTest, Invalid) { 36 QueryRef Q = parse("foo"); 37 ASSERT_TRUE(isa<InvalidQuery>(Q)); 38 EXPECT_EQ("unknown command: foo", cast<InvalidQuery>(Q)->ErrStr); 39 } 40 41 TEST_F(QueryParserTest, Help) { 42 QueryRef Q = parse("help"); 43 ASSERT_TRUE(isa<HelpQuery>(Q)); 44 45 Q = parse("help me"); 46 ASSERT_TRUE(isa<InvalidQuery>(Q)); 47 EXPECT_EQ("unexpected extra input: ' me'", cast<InvalidQuery>(Q)->ErrStr); 48 } 49 50 TEST_F(QueryParserTest, Quit) { 51 QueryRef Q = parse("quit"); 52 ASSERT_TRUE(isa<QuitQuery>(Q)); 53 54 Q = parse("q"); 55 ASSERT_TRUE(isa<QuitQuery>(Q)); 56 57 Q = parse("quit me"); 58 ASSERT_TRUE(isa<InvalidQuery>(Q)); 59 EXPECT_EQ("unexpected extra input: ' me'", cast<InvalidQuery>(Q)->ErrStr); 60 } 61 62 TEST_F(QueryParserTest, Set) { 63 QueryRef Q = parse("set"); 64 ASSERT_TRUE(isa<InvalidQuery>(Q)); 65 EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr); 66 67 Q = parse("set foo bar"); 68 ASSERT_TRUE(isa<InvalidQuery>(Q)); 69 EXPECT_EQ("unknown variable: 'foo'", cast<InvalidQuery>(Q)->ErrStr); 70 71 Q = parse("set output"); 72 ASSERT_TRUE(isa<InvalidQuery>(Q)); 73 EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''", 74 cast<InvalidQuery>(Q)->ErrStr); 75 76 Q = parse("set bind-root true foo"); 77 ASSERT_TRUE(isa<InvalidQuery>(Q)); 78 EXPECT_EQ("unexpected extra input: ' foo'", cast<InvalidQuery>(Q)->ErrStr); 79 80 Q = parse("set output foo"); 81 ASSERT_TRUE(isa<InvalidQuery>(Q)); 82 EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'", 83 cast<InvalidQuery>(Q)->ErrStr); 84 85 Q = parse("set output dump"); 86 ASSERT_TRUE(isa<SetExclusiveOutputQuery >(Q)); 87 EXPECT_EQ(&QuerySession::DetailedASTOutput, cast<SetExclusiveOutputQuery>(Q)->Var); 88 89 Q = parse("set output detailed-ast"); 90 ASSERT_TRUE(isa<SetExclusiveOutputQuery>(Q)); 91 EXPECT_EQ(&QuerySession::DetailedASTOutput, cast<SetExclusiveOutputQuery>(Q)->Var); 92 93 Q = parse("set bind-root foo"); 94 ASSERT_TRUE(isa<InvalidQuery>(Q)); 95 EXPECT_EQ("expected 'true' or 'false', got 'foo'", 96 cast<InvalidQuery>(Q)->ErrStr); 97 98 Q = parse("set bind-root true"); 99 ASSERT_TRUE(isa<SetQuery<bool> >(Q)); 100 EXPECT_EQ(&QuerySession::BindRoot, cast<SetQuery<bool> >(Q)->Var); 101 EXPECT_EQ(true, cast<SetQuery<bool> >(Q)->Value); 102 } 103 104 TEST_F(QueryParserTest, Match) { 105 QueryRef Q = parse("match decl()"); 106 ASSERT_TRUE(isa<MatchQuery>(Q)); 107 EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Decl>()); 108 109 Q = parse("m stmt()"); 110 ASSERT_TRUE(isa<MatchQuery>(Q)); 111 EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Stmt>()); 112 } 113 114 TEST_F(QueryParserTest, LetUnlet) { 115 QueryRef Q = parse("let foo decl()"); 116 ASSERT_TRUE(isa<LetQuery>(Q)); 117 EXPECT_EQ("foo", cast<LetQuery>(Q)->Name); 118 EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher()); 119 EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>()); 120 121 Q = parse("l foo decl()"); 122 ASSERT_TRUE(isa<LetQuery>(Q)); 123 EXPECT_EQ("foo", cast<LetQuery>(Q)->Name); 124 EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher()); 125 EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>()); 126 127 Q = parse("let bar \"str\""); 128 ASSERT_TRUE(isa<LetQuery>(Q)); 129 EXPECT_EQ("bar", cast<LetQuery>(Q)->Name); 130 EXPECT_TRUE(cast<LetQuery>(Q)->Value.isString()); 131 EXPECT_EQ("str", cast<LetQuery>(Q)->Value.getString()); 132 133 Q = parse("let"); 134 ASSERT_TRUE(isa<InvalidQuery>(Q)); 135 EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr); 136 137 Q = parse("unlet x"); 138 ASSERT_TRUE(isa<LetQuery>(Q)); 139 EXPECT_EQ("x", cast<LetQuery>(Q)->Name); 140 EXPECT_FALSE(cast<LetQuery>(Q)->Value.hasValue()); 141 142 Q = parse("unlet"); 143 ASSERT_TRUE(isa<InvalidQuery>(Q)); 144 EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr); 145 146 Q = parse("unlet x bad_data"); 147 ASSERT_TRUE(isa<InvalidQuery>(Q)); 148 EXPECT_EQ("unexpected extra input: ' bad_data'", 149 cast<InvalidQuery>(Q)->ErrStr); 150 } 151 152 TEST_F(QueryParserTest, Comment) { 153 QueryRef Q = parse("# let foo decl()"); 154 ASSERT_TRUE(isa<NoOpQuery>(Q)); 155 156 Q = parse("let foo decl() # creates a decl() matcher called foo"); 157 ASSERT_TRUE(isa<LetQuery>(Q)); 158 159 Q = parse("set bind-root false # reduce noise"); 160 ASSERT_TRUE(isa<SetQuery<bool>>(Q)); 161 } 162 163 TEST_F(QueryParserTest, Complete) { 164 std::vector<llvm::LineEditor::Completion> Comps = 165 QueryParser::complete("", 0, QS); 166 ASSERT_EQ(6u, Comps.size()); 167 EXPECT_EQ("help ", Comps[0].TypedText); 168 EXPECT_EQ("help", Comps[0].DisplayText); 169 EXPECT_EQ("let ", Comps[1].TypedText); 170 EXPECT_EQ("let", Comps[1].DisplayText); 171 EXPECT_EQ("match ", Comps[2].TypedText); 172 EXPECT_EQ("match", Comps[2].DisplayText); 173 EXPECT_EQ("quit ", Comps[3].TypedText); 174 EXPECT_EQ("quit", Comps[3].DisplayText); 175 EXPECT_EQ("set ", Comps[4].TypedText); 176 EXPECT_EQ("set", Comps[4].DisplayText); 177 EXPECT_EQ("unlet ", Comps[5].TypedText); 178 EXPECT_EQ("unlet", Comps[5].DisplayText); 179 180 Comps = QueryParser::complete("set o", 5, QS); 181 ASSERT_EQ(1u, Comps.size()); 182 EXPECT_EQ("utput ", Comps[0].TypedText); 183 EXPECT_EQ("output", Comps[0].DisplayText); 184 185 Comps = QueryParser::complete("match while", 11, QS); 186 ASSERT_EQ(1u, Comps.size()); 187 EXPECT_EQ("Stmt(", Comps[0].TypedText); 188 EXPECT_EQ("Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)", 189 Comps[0].DisplayText); 190 191 Comps = QueryParser::complete("m", 1, QS); 192 ASSERT_EQ(1u, Comps.size()); 193 EXPECT_EQ("atch ", Comps[0].TypedText); 194 EXPECT_EQ("match", Comps[0].DisplayText); 195 196 Comps = QueryParser::complete("l", 1, QS); 197 ASSERT_EQ(1u, Comps.size()); 198 EXPECT_EQ("et ", Comps[0].TypedText); 199 EXPECT_EQ("let", Comps[0].DisplayText); 200 } 201