[clang-tools-extra] r206984 - Add new 'let' command to bind arbitrary values into constants.
Samuel Benzaquen
sbenza at google.com
Wed Apr 23 07:04:53 PDT 2014
Author: sbenza
Date: Wed Apr 23 09:04:52 2014
New Revision: 206984
URL: http://llvm.org/viewvc/llvm-project?rev=206984&view=rev
Log:
Add new 'let' command to bind arbitrary values into constants.
Summary:
Add new 'let' command to bind arbitrary values into constants.
These constants can then be used in the matcher expressions.
Reviewers: pcc
CC: cfe-commits
Differential Revision: http://reviews.llvm.org/D3383
Modified:
clang-tools-extra/trunk/clang-query/Query.cpp
clang-tools-extra/trunk/clang-query/Query.h
clang-tools-extra/trunk/clang-query/QueryParser.cpp
clang-tools-extra/trunk/clang-query/QueryParser.h
clang-tools-extra/trunk/clang-query/QuerySession.h
clang-tools-extra/trunk/clang-query/tool/ClangQuery.cpp
clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp
clang-tools-extra/trunk/unittests/clang-query/QueryParserTest.cpp
Modified: clang-tools-extra/trunk/clang-query/Query.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-query/Query.cpp?rev=206984&r1=206983&r2=206984&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-query/Query.cpp (original)
+++ clang-tools-extra/trunk/clang-query/Query.cpp Wed Apr 23 09:04:52 2014
@@ -54,7 +54,7 @@ struct CollectBoundNodes : MatchFinder::
}
};
-}
+} // namespace
bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
unsigned MatchCount = 0;
@@ -124,6 +124,15 @@ bool MatchQuery::run(llvm::raw_ostream &
return true;
}
+bool LetQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
+ if (Value) {
+ QS.NamedValues[Name] = Value;
+ } else {
+ QS.NamedValues.erase(Name);
+ }
+ return true;
+}
+
#ifndef _MSC_VER
const QueryKind SetQueryKind<bool>::value;
const QueryKind SetQueryKind<OutputKind>::value;
Modified: clang-tools-extra/trunk/clang-query/Query.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-query/Query.h?rev=206984&r1=206983&r2=206984&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-query/Query.h (original)
+++ clang-tools-extra/trunk/clang-query/Query.h Wed Apr 23 09:04:52 2014
@@ -28,9 +28,10 @@ enum QueryKind {
QK_Invalid,
QK_NoOp,
QK_Help,
+ QK_Let,
QK_Match,
QK_SetBool,
- QK_SetOutputKind
+ QK_SetOutputKind,
};
class QuerySession;
@@ -86,6 +87,17 @@ struct MatchQuery : Query {
static bool classof(const Query *Q) { return Q->Kind == QK_Match; }
};
+struct LetQuery : Query {
+ LetQuery(StringRef Name, const ast_matchers::dynamic::VariantValue &Value)
+ : Query(QK_Let), Name(Name), Value(Value) {}
+ bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
+
+ std::string Name;
+ ast_matchers::dynamic::VariantValue Value;
+
+ static bool classof(const Query *Q) { return Q->Kind == QK_Let; }
+};
+
template <typename T> struct SetQueryKind {};
template <> struct SetQueryKind<bool> {
Modified: clang-tools-extra/trunk/clang-query/QueryParser.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-query/QueryParser.cpp?rev=206984&r1=206983&r2=206984&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-query/QueryParser.cpp (original)
+++ clang-tools-extra/trunk/clang-query/QueryParser.cpp Wed Apr 23 09:04:52 2014
@@ -132,12 +132,16 @@ QueryRef QueryParser::endQuery(QueryRef
return Q;
}
+namespace {
+
enum ParsedQueryKind {
PQK_Invalid,
PQK_NoOp,
PQK_Help,
+ PQK_Let,
PQK_Match,
- PQK_Set
+ PQK_Set,
+ PQK_Unlet,
};
enum ParsedQueryVariable {
@@ -146,16 +150,52 @@ enum ParsedQueryVariable {
PQV_BindRoot
};
+QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) {
+ std::string ErrStr;
+ llvm::raw_string_ostream OS(ErrStr);
+ Diag.printToStreamFull(OS);
+ return new InvalidQuery(OS.str());
+}
+
+class QuerySessionSema : public Parser::RegistrySema {
+public:
+ QuerySessionSema(const QuerySession &QS) : QS(QS) {}
+
+ ast_matchers::dynamic::VariantValue getNamedValue(StringRef Name) override {
+ return QS.NamedValues.lookup(Name);
+ }
+
+private:
+ const QuerySession &QS;
+};
+
+} // namespace
+
+QueryRef QueryParser::completeMatcherExpression() {
+ std::vector<MatcherCompletion> Comps = Parser::completeExpression(
+ StringRef(Begin, End - Begin), CompletionPos - Begin);
+ for (std::vector<MatcherCompletion>::iterator I = Comps.begin(),
+ E = Comps.end();
+ I != E; ++I) {
+ Completions.push_back(LineEditor::Completion(I->TypedText, I->MatcherDecl));
+ }
+ return QueryRef();
+}
+
QueryRef QueryParser::doParse() {
StringRef CommandStr;
ParsedQueryKind QKind = lexOrCompleteWord<ParsedQueryKind>(CommandStr)
.Case("", PQK_NoOp)
.Case("help", PQK_Help)
.Case("m", PQK_Match, /*IsCompletion=*/false)
+ .Case("let", PQK_Let)
.Case("match", PQK_Match)
.Case("set", PQK_Set)
+ .Case("unlet", PQK_Unlet)
.Default(PQK_Invalid);
+ QuerySessionSema S(QS);
+
switch (QKind) {
case PQK_NoOp:
return new NoOpQuery;
@@ -163,29 +203,36 @@ QueryRef QueryParser::doParse() {
case PQK_Help:
return endQuery(new HelpQuery);
+ case PQK_Let: {
+ StringRef Name = lexWord();
+
+ if (Name.empty())
+ return new InvalidQuery("expected variable name");
+
+ if (CompletionPos)
+ return completeMatcherExpression();
+
+ Diagnostics Diag;
+ ast_matchers::dynamic::VariantValue Value;
+ if (!Parser::parseExpression(StringRef(Begin, End - Begin), &S, &Value,
+ &Diag)) {
+ return makeInvalidQueryFromDiagnostics(Diag);
+ }
+
+ return new LetQuery(Name, Value);
+ }
+
case PQK_Match: {
- if (CompletionPos) {
- std::vector<MatcherCompletion> Comps = Parser::completeExpression(
- StringRef(Begin, End - Begin), CompletionPos - Begin);
- for (std::vector<MatcherCompletion>::iterator I = Comps.begin(),
- E = Comps.end();
- I != E; ++I) {
- Completions.push_back(
- LineEditor::Completion(I->TypedText, I->MatcherDecl));
- }
- return QueryRef();
- } else {
- Diagnostics Diag;
- Optional<DynTypedMatcher> Matcher =
- Parser::parseMatcherExpression(StringRef(Begin, End - Begin), &Diag);
- if (!Matcher) {
- std::string ErrStr;
- llvm::raw_string_ostream OS(ErrStr);
- Diag.printToStreamFull(OS);
- return new InvalidQuery(OS.str());
- }
- return new MatchQuery(*Matcher);
+ if (CompletionPos)
+ return completeMatcherExpression();
+
+ Diagnostics Diag;
+ Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
+ StringRef(Begin, End - Begin), &S, &Diag);
+ if (!Matcher) {
+ return makeInvalidQueryFromDiagnostics(Diag);
}
+ return new MatchQuery(*Matcher);
}
case PQK_Set: {
@@ -214,6 +261,15 @@ QueryRef QueryParser::doParse() {
return endQuery(Q);
}
+ case PQK_Unlet: {
+ StringRef Name = lexWord();
+
+ if (Name.empty())
+ return new InvalidQuery("expected variable name");
+
+ return endQuery(new LetQuery(Name, {}));
+ }
+
case PQK_Invalid:
return new InvalidQuery("unknown command: " + CommandStr);
}
@@ -221,13 +277,13 @@ QueryRef QueryParser::doParse() {
llvm_unreachable("Invalid query kind");
}
-QueryRef QueryParser::parse(StringRef Line) {
- return QueryParser(Line).doParse();
+QueryRef QueryParser::parse(StringRef Line, const QuerySession &QS) {
+ return QueryParser(Line, QS).doParse();
}
-std::vector<LineEditor::Completion> QueryParser::complete(StringRef Line,
- size_t Pos) {
- QueryParser P(Line);
+std::vector<LineEditor::Completion>
+QueryParser::complete(StringRef Line, size_t Pos, const QuerySession &QS) {
+ QueryParser P(Line, QS);
P.CompletionPos = Line.data() + Pos;
P.doParse();
Modified: clang-tools-extra/trunk/clang-query/QueryParser.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-query/QueryParser.h?rev=206984&r1=206983&r2=206984&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-query/QueryParser.h (original)
+++ clang-tools-extra/trunk/clang-query/QueryParser.h Wed Apr 23 09:04:52 2014
@@ -11,6 +11,7 @@
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_PARSER_H
#include "Query.h"
+#include "QuerySession.h"
#include "llvm/LineEditor/LineEditor.h"
#include <stddef.h>
@@ -24,19 +25,20 @@ public:
/// Parse \a Line as a query.
///
/// \return A QueryRef representing the query, which may be an InvalidQuery.
- static QueryRef parse(StringRef Line);
+ static QueryRef parse(StringRef Line, const QuerySession &QS);
/// Compute a list of completions for \a Line assuming a cursor at
/// \param Pos characters past the start of \a Line, ordered from most
/// likely to least likely.
///
/// \return A vector of completions for \a Line.
- static std::vector<llvm::LineEditor::Completion> complete(StringRef Line,
- size_t Pos);
+ static std::vector<llvm::LineEditor::Completion>
+ complete(StringRef Line, size_t Pos, const QuerySession &QS);
private:
- QueryParser(StringRef Line)
- : Begin(Line.data()), End(Line.data() + Line.size()), CompletionPos(0) {}
+ QueryParser(StringRef Line, const QuerySession &QS)
+ : Begin(Line.data()), End(Line.data() + Line.size()), CompletionPos(0),
+ QS(QS) {}
StringRef lexWord();
@@ -45,6 +47,7 @@ private:
QueryRef parseSetBool(bool QuerySession::*Var);
QueryRef parseSetOutputKind();
+ QueryRef completeMatcherExpression();
QueryRef endQuery(QueryRef Q);
@@ -59,6 +62,8 @@ private:
const char *CompletionPos;
std::vector<llvm::LineEditor::Completion> Completions;
+
+ const QuerySession &QS;
};
} // namespace query
Modified: clang-tools-extra/trunk/clang-query/QuerySession.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-query/QuerySession.h?rev=206984&r1=206983&r2=206984&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-query/QuerySession.h (original)
+++ clang-tools-extra/trunk/clang-query/QuerySession.h Wed Apr 23 09:04:52 2014
@@ -11,7 +11,9 @@
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_SESSION_H
#include "Query.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringMap.h"
namespace clang {
@@ -28,6 +30,7 @@ public:
llvm::ArrayRef<ASTUnit *> ASTs;
OutputKind OutKind;
bool BindRoot;
+ llvm::StringMap<ast_matchers::dynamic::VariantValue> NamedValues;
};
} // namespace query
Modified: clang-tools-extra/trunk/clang-query/tool/ClangQuery.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-query/tool/ClangQuery.cpp?rev=206984&r1=206983&r2=206984&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-query/tool/ClangQuery.cpp (original)
+++ clang-tools-extra/trunk/clang-query/tool/ClangQuery.cpp Wed Apr 23 09:04:52 2014
@@ -95,7 +95,7 @@ int main(int argc, const char **argv) {
for (cl::list<std::string>::iterator I = Commands.begin(),
E = Commands.end();
I != E; ++I) {
- QueryRef Q = QueryParser::parse(I->c_str());
+ QueryRef Q = QueryParser::parse(I->c_str(), QS);
if (!Q->run(llvm::outs(), QS))
return 1;
}
@@ -112,16 +112,18 @@ int main(int argc, const char **argv) {
std::string Line;
std::getline(Input, Line);
- QueryRef Q = QueryParser::parse(Line.c_str());
+ QueryRef Q = QueryParser::parse(Line.c_str(), QS);
if (!Q->run(llvm::outs(), QS))
return 1;
}
}
} else {
LineEditor LE("clang-query");
- LE.setListCompleter(QueryParser::complete);
+ LE.setListCompleter([&QS](StringRef Line, size_t Pos) {
+ return QueryParser::complete(Line, Pos, QS);
+ });
while (llvm::Optional<std::string> Line = LE.readLine()) {
- QueryRef Q = QueryParser::parse(*Line);
+ QueryRef Q = QueryParser::parse(*Line, QS);
Q->run(llvm::outs(), QS);
}
}
Modified: clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp?rev=206984&r1=206983&r2=206984&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-query/QueryEngineTest.cpp Wed Apr 23 09:04:52 2014
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "Query.h"
+#include "QueryParser.h"
#include "QuerySession.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
@@ -24,20 +25,22 @@ using namespace clang::ast_matchers::dyn
using namespace clang::query;
using namespace clang::tooling;
-TEST(Query, Basic) {
- std::unique_ptr<ASTUnit> FooAST(
- buildASTFromCode("void foo1(void) {}\nvoid foo2(void) {}", "foo.cc"));
- ASSERT_TRUE(FooAST.get());
- std::unique_ptr<ASTUnit> BarAST(
- buildASTFromCode("void bar1(void) {}\nvoid bar2(void) {}", "bar.cc"));
- ASSERT_TRUE(BarAST.get());
-
- ASTUnit *ASTs[] = { FooAST.get(), BarAST.get() };
+class QueryEngineTest : public ::testing::Test {
+protected:
+ QueryEngineTest() {}
+
+ std::unique_ptr<ASTUnit> FooAST{
+ buildASTFromCode("void foo1(void) {}\nvoid foo2(void) {}", "foo.cc")};
+ std::unique_ptr<ASTUnit> BarAST{
+ buildASTFromCode("void bar1(void) {}\nvoid bar2(void) {}", "bar.cc")};
+ ASTUnit *ASTs[2]{FooAST.get(), BarAST.get()};
+ QuerySession S{ASTs};
std::string Str;
- llvm::raw_string_ostream OS(Str);
- QuerySession S(ASTs);
+ llvm::raw_string_ostream OS{Str};
+};
+TEST_F(QueryEngineTest, Basic) {
DynTypedMatcher FnMatcher = functionDecl();
DynTypedMatcher FooMatcher = functionDecl(hasName("foo1"));
@@ -108,3 +111,28 @@ TEST(Query, Basic) {
EXPECT_EQ("Not a valid top-level matcher.\n", OS.str());
}
+
+TEST_F(QueryEngineTest, LetAndMatch) {
+ EXPECT_TRUE(QueryParser::parse("let x \"foo1\"", S)->run(OS, S));
+ EXPECT_EQ("", OS.str());
+ Str.clear();
+
+ EXPECT_TRUE(QueryParser::parse("let y hasName(x)", S)->run(OS, S));
+ EXPECT_EQ("", OS.str());
+ Str.clear();
+
+ EXPECT_TRUE(QueryParser::parse("match functionDecl(y)", S)->run(OS, S));
+ EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=
+ std::string::npos);
+ EXPECT_TRUE(OS.str().find("1 match.") != std::string::npos);
+ Str.clear();
+
+ EXPECT_TRUE(QueryParser::parse("unlet x", S)->run(OS, S));
+ EXPECT_EQ("", OS.str());
+ Str.clear();
+
+ EXPECT_FALSE(QueryParser::parse("let y hasName(x)", S)->run(OS, S));
+ EXPECT_EQ("1:2: Error parsing argument 1 for matcher hasName.\n"
+ "1:10: Value not found: x\n", OS.str());
+ Str.clear();
+}
Modified: clang-tools-extra/trunk/unittests/clang-query/QueryParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-query/QueryParserTest.cpp?rev=206984&r1=206983&r2=206984&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-query/QueryParserTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-query/QueryParserTest.cpp Wed Apr 23 09:04:52 2014
@@ -16,95 +16,139 @@
using namespace clang;
using namespace clang::query;
-TEST(QueryParser, NoOp) {
- QueryRef Q = QueryParser::parse("");
+class QueryParserTest : public ::testing::Test {
+protected:
+ QueryParserTest() {}
+ QueryRef parse(StringRef Code) { return QueryParser::parse(Code, QS); }
+
+ QuerySession QS{llvm::ArrayRef<ASTUnit*>()};
+};
+
+TEST_F(QueryParserTest, NoOp) {
+ QueryRef Q = parse("");
EXPECT_TRUE(isa<NoOpQuery>(Q));
- Q = QueryParser::parse("\n");
+ Q = parse("\n");
EXPECT_TRUE(isa<NoOpQuery>(Q));
}
-TEST(QueryParser, Invalid) {
- QueryRef Q = QueryParser::parse("foo");
+TEST_F(QueryParserTest, Invalid) {
+ QueryRef Q = parse("foo");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("unknown command: foo", cast<InvalidQuery>(Q)->ErrStr);
}
-TEST(QueryParser, Help) {
- QueryRef Q = QueryParser::parse("help");
+TEST_F(QueryParserTest, Help) {
+ QueryRef Q = parse("help");
ASSERT_TRUE(isa<HelpQuery>(Q));
- Q = QueryParser::parse("help me");
+ Q = parse("help me");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("unexpected extra input: ' me'", cast<InvalidQuery>(Q)->ErrStr);
}
-TEST(QueryParser, Set) {
- QueryRef Q = QueryParser::parse("set");
+TEST_F(QueryParserTest, Set) {
+ QueryRef Q = parse("set");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);
- Q = QueryParser::parse("set foo bar");
+ Q = parse("set foo bar");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("unknown variable: 'foo'", cast<InvalidQuery>(Q)->ErrStr);
- Q = QueryParser::parse("set output");
+ Q = parse("set output");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("expected 'diag', 'print' or 'dump', got ''",
cast<InvalidQuery>(Q)->ErrStr);
- Q = QueryParser::parse("set bind-root true foo");
+ Q = parse("set bind-root true foo");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("unexpected extra input: ' foo'", cast<InvalidQuery>(Q)->ErrStr);
- Q = QueryParser::parse("set output foo");
+ Q = parse("set output foo");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("expected 'diag', 'print' or 'dump', got 'foo'",
cast<InvalidQuery>(Q)->ErrStr);
- Q = QueryParser::parse("set output dump");
+ Q = parse("set output dump");
ASSERT_TRUE(isa<SetQuery<OutputKind> >(Q));
EXPECT_EQ(&QuerySession::OutKind, cast<SetQuery<OutputKind> >(Q)->Var);
EXPECT_EQ(OK_Dump, cast<SetQuery<OutputKind> >(Q)->Value);
- Q = QueryParser::parse("set bind-root foo");
+ Q = parse("set bind-root foo");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("expected 'true' or 'false', got 'foo'",
cast<InvalidQuery>(Q)->ErrStr);
- Q = QueryParser::parse("set bind-root true");
+ Q = parse("set bind-root true");
ASSERT_TRUE(isa<SetQuery<bool> >(Q));
EXPECT_EQ(&QuerySession::BindRoot, cast<SetQuery<bool> >(Q)->Var);
EXPECT_EQ(true, cast<SetQuery<bool> >(Q)->Value);
}
-TEST(QueryParser, Match) {
- QueryRef Q = QueryParser::parse("match decl()");
+TEST_F(QueryParserTest, Match) {
+ QueryRef Q = parse("match decl()");
ASSERT_TRUE(isa<MatchQuery>(Q));
EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Decl>());
- Q = QueryParser::parse("m stmt()");
+ Q = parse("m stmt()");
ASSERT_TRUE(isa<MatchQuery>(Q));
EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Stmt>());
}
-TEST(QueryParser, Complete) {
+TEST_F(QueryParserTest, LetUnlet) {
+ QueryRef Q = parse("let foo decl()");
+ ASSERT_TRUE(isa<LetQuery>(Q));
+ EXPECT_EQ("foo", cast<LetQuery>(Q)->Name);
+ EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher());
+ EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>());
+
+ Q = parse("let bar \"str\"");
+ ASSERT_TRUE(isa<LetQuery>(Q));
+ EXPECT_EQ("bar", cast<LetQuery>(Q)->Name);
+ EXPECT_TRUE(cast<LetQuery>(Q)->Value.isString());
+ EXPECT_EQ("str", cast<LetQuery>(Q)->Value.getString());
+
+ Q = parse("let");
+ ASSERT_TRUE(isa<InvalidQuery>(Q));
+ EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);
+
+ Q = parse("unlet x");
+ ASSERT_TRUE(isa<LetQuery>(Q));
+ EXPECT_EQ("x", cast<LetQuery>(Q)->Name);
+ EXPECT_FALSE(cast<LetQuery>(Q)->Value.hasValue());
+
+ Q = parse("unlet");
+ ASSERT_TRUE(isa<InvalidQuery>(Q));
+ EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);
+
+ Q = parse("unlet x bad_data");
+ ASSERT_TRUE(isa<InvalidQuery>(Q));
+ EXPECT_EQ("unexpected extra input: ' bad_data'",
+ cast<InvalidQuery>(Q)->ErrStr);
+}
+
+TEST_F(QueryParserTest, Complete) {
std::vector<llvm::LineEditor::Completion> Comps =
- QueryParser::complete("", 0);
- ASSERT_EQ(3u, Comps.size());
+ QueryParser::complete("", 0, QS);
+ ASSERT_EQ(5u, Comps.size());
EXPECT_EQ("help ", Comps[0].TypedText);
EXPECT_EQ("help", Comps[0].DisplayText);
- EXPECT_EQ("match ", Comps[1].TypedText);
- EXPECT_EQ("match", Comps[1].DisplayText);
- EXPECT_EQ("set ", Comps[2].TypedText);
- EXPECT_EQ("set", Comps[2].DisplayText);
+ EXPECT_EQ("let ", Comps[1].TypedText);
+ EXPECT_EQ("let", Comps[1].DisplayText);
+ EXPECT_EQ("match ", Comps[2].TypedText);
+ EXPECT_EQ("match", Comps[2].DisplayText);
+ EXPECT_EQ("set ", Comps[3].TypedText);
+ EXPECT_EQ("set", Comps[3].DisplayText);
+ EXPECT_EQ("unlet ", Comps[4].TypedText);
+ EXPECT_EQ("unlet", Comps[4].DisplayText);
- Comps = QueryParser::complete("set o", 5);
+ Comps = QueryParser::complete("set o", 5, QS);
ASSERT_EQ(1u, Comps.size());
EXPECT_EQ("utput ", Comps[0].TypedText);
EXPECT_EQ("output", Comps[0].DisplayText);
- Comps = QueryParser::complete("match while", 11);
+ Comps = QueryParser::complete("match while", 11, QS);
ASSERT_EQ(1u, Comps.size());
EXPECT_EQ("Stmt(", Comps[0].TypedText);
EXPECT_EQ("Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)",
More information about the cfe-commits
mailing list