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("enable output detailed-ast"); 94 ASSERT_TRUE(isa<EnableOutputQuery>(Q)); 95 EXPECT_EQ(&QuerySession::DetailedASTOutput, cast<EnableOutputQuery>(Q)->Var); 96 97 Q = parse("enable"); 98 ASSERT_TRUE(isa<InvalidQuery>(Q)); 99 EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr); 100 101 Q = parse("disable output detailed-ast"); 102 ASSERT_TRUE(isa<DisableOutputQuery>(Q)); 103 EXPECT_EQ(&QuerySession::DetailedASTOutput, cast<DisableOutputQuery>(Q)->Var); 104 105 Q = parse("set bind-root foo"); 106 ASSERT_TRUE(isa<InvalidQuery>(Q)); 107 EXPECT_EQ("expected 'true' or 'false', got 'foo'", 108 cast<InvalidQuery>(Q)->ErrStr); 109 110 Q = parse("set bind-root true"); 111 ASSERT_TRUE(isa<SetQuery<bool> >(Q)); 112 EXPECT_EQ(&QuerySession::BindRoot, cast<SetQuery<bool> >(Q)->Var); 113 EXPECT_EQ(true, cast<SetQuery<bool> >(Q)->Value); 114 } 115 116 TEST_F(QueryParserTest, Match) { 117 QueryRef Q = parse("match decl()"); 118 ASSERT_TRUE(isa<MatchQuery>(Q)); 119 EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Decl>()); 120 121 Q = parse("m stmt()"); 122 ASSERT_TRUE(isa<MatchQuery>(Q)); 123 EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Stmt>()); 124 } 125 126 TEST_F(QueryParserTest, LetUnlet) { 127 QueryRef Q = parse("let foo decl()"); 128 ASSERT_TRUE(isa<LetQuery>(Q)); 129 EXPECT_EQ("foo", cast<LetQuery>(Q)->Name); 130 EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher()); 131 EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>()); 132 133 Q = parse("l foo decl()"); 134 ASSERT_TRUE(isa<LetQuery>(Q)); 135 EXPECT_EQ("foo", cast<LetQuery>(Q)->Name); 136 EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher()); 137 EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>()); 138 139 Q = parse("let bar \"str\""); 140 ASSERT_TRUE(isa<LetQuery>(Q)); 141 EXPECT_EQ("bar", cast<LetQuery>(Q)->Name); 142 EXPECT_TRUE(cast<LetQuery>(Q)->Value.isString()); 143 EXPECT_EQ("str", cast<LetQuery>(Q)->Value.getString()); 144 145 Q = parse("let"); 146 ASSERT_TRUE(isa<InvalidQuery>(Q)); 147 EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr); 148 149 Q = parse("unlet x"); 150 ASSERT_TRUE(isa<LetQuery>(Q)); 151 EXPECT_EQ("x", cast<LetQuery>(Q)->Name); 152 EXPECT_FALSE(cast<LetQuery>(Q)->Value.hasValue()); 153 154 Q = parse("unlet"); 155 ASSERT_TRUE(isa<InvalidQuery>(Q)); 156 EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr); 157 158 Q = parse("unlet x bad_data"); 159 ASSERT_TRUE(isa<InvalidQuery>(Q)); 160 EXPECT_EQ("unexpected extra input: ' bad_data'", 161 cast<InvalidQuery>(Q)->ErrStr); 162 } 163 164 TEST_F(QueryParserTest, Comment) { 165 QueryRef Q = parse("# let foo decl()"); 166 ASSERT_TRUE(isa<NoOpQuery>(Q)); 167 168 Q = parse("let foo decl() # creates a decl() matcher called foo"); 169 ASSERT_TRUE(isa<LetQuery>(Q)); 170 171 Q = parse("set bind-root false # reduce noise"); 172 ASSERT_TRUE(isa<SetQuery<bool>>(Q)); 173 } 174 175 TEST_F(QueryParserTest, Complete) { 176 std::vector<llvm::LineEditor::Completion> Comps = 177 QueryParser::complete("", 0, QS); 178 ASSERT_EQ(8u, Comps.size()); 179 EXPECT_EQ("help ", Comps[0].TypedText); 180 EXPECT_EQ("help", Comps[0].DisplayText); 181 EXPECT_EQ("let ", Comps[1].TypedText); 182 EXPECT_EQ("let", Comps[1].DisplayText); 183 EXPECT_EQ("match ", Comps[2].TypedText); 184 EXPECT_EQ("match", Comps[2].DisplayText); 185 EXPECT_EQ("quit ", Comps[3].TypedText); 186 EXPECT_EQ("quit", Comps[3].DisplayText); 187 EXPECT_EQ("set ", Comps[4].TypedText); 188 EXPECT_EQ("set", Comps[4].DisplayText); 189 EXPECT_EQ("enable ", Comps[5].TypedText); 190 EXPECT_EQ("enable", Comps[5].DisplayText); 191 EXPECT_EQ("disable ", Comps[6].TypedText); 192 EXPECT_EQ("disable", Comps[6].DisplayText); 193 EXPECT_EQ("unlet ", Comps[7].TypedText); 194 EXPECT_EQ("unlet", Comps[7].DisplayText); 195 196 Comps = QueryParser::complete("set o", 5, QS); 197 ASSERT_EQ(1u, Comps.size()); 198 EXPECT_EQ("utput ", Comps[0].TypedText); 199 EXPECT_EQ("output", Comps[0].DisplayText); 200 201 Comps = QueryParser::complete("enable ", 7, QS); 202 ASSERT_EQ(1u, Comps.size()); 203 EXPECT_EQ("output ", Comps[0].TypedText); 204 EXPECT_EQ("output", Comps[0].DisplayText); 205 206 Comps = QueryParser::complete("enable output ", 14, QS); 207 ASSERT_EQ(4u, Comps.size()); 208 209 EXPECT_EQ("diag ", Comps[0].TypedText); 210 EXPECT_EQ("diag", Comps[0].DisplayText); 211 EXPECT_EQ("print ", Comps[1].TypedText); 212 EXPECT_EQ("print", Comps[1].DisplayText); 213 EXPECT_EQ("detailed-ast ", Comps[2].TypedText); 214 EXPECT_EQ("detailed-ast", Comps[2].DisplayText); 215 EXPECT_EQ("dump ", Comps[3].TypedText); 216 EXPECT_EQ("dump", Comps[3].DisplayText); 217 218 Comps = QueryParser::complete("match while", 11, QS); 219 ASSERT_EQ(1u, Comps.size()); 220 EXPECT_EQ("Stmt(", Comps[0].TypedText); 221 EXPECT_EQ("Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)", 222 Comps[0].DisplayText); 223 224 Comps = QueryParser::complete("m", 1, QS); 225 ASSERT_EQ(1u, Comps.size()); 226 EXPECT_EQ("atch ", Comps[0].TypedText); 227 EXPECT_EQ("match", Comps[0].DisplayText); 228 229 Comps = QueryParser::complete("l", 1, QS); 230 ASSERT_EQ(1u, Comps.size()); 231 EXPECT_EQ("et ", Comps[0].TypedText); 232 EXPECT_EQ("let", Comps[0].DisplayText); 233 } 234