diff --git a/clang-tools-extra/clang-query/Query.h b/clang-tools-extra/clang-query/Query.h --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -149,6 +149,7 @@ QS.DiagOutput = false; QS.DetailedASTOutput = false; QS.PrintOutput = false; + QS.SrcLocOutput = false; QS.*Var = true; return true; } diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -11,6 +11,7 @@ #include "QuerySession.h" #include "clang/ASTMatchers/Dynamic/Parser.h" #include "clang/Basic/CharInfo.h" +#include "clang/Tooling/NodeIntrospection.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include @@ -104,17 +105,19 @@ template QueryRef QueryParser::parseSetOutputKind() { StringRef ValStr; - unsigned OutKind = LexOrCompleteWord(this, ValStr) - .Case("diag", OK_Diag) - .Case("print", OK_Print) - .Case("detailed-ast", OK_DetailedAST) - .Case("srcloc", OK_SrcLoc) - .Case("dump", OK_DetailedAST) - .Default(~0u); + bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport(); + unsigned OutKind = + LexOrCompleteWord(this, ValStr) + .Case("diag", OK_Diag) + .Case("print", OK_Print) + .Case("detailed-ast", OK_DetailedAST) + .Case("srcloc", OK_SrcLoc, /*IsCompletion=*/HasIntrospection) + .Case("dump", OK_DetailedAST) + .Default(~0u); if (OutKind == ~0u) { - return new InvalidQuery( - "expected 'diag', 'print', 'detailed-ast' or 'dump', got '" + ValStr + - "'"); + return new InvalidQuery("expected 'diag', 'print', 'detailed-ast'" + + StringRef(HasIntrospection ? ", 'srcloc'" : "") + + " or 'dump', got '" + ValStr + "'"); } switch (OutKind) { @@ -125,7 +128,9 @@ case OK_Print: return new QueryType(&QuerySession::PrintOutput); case OK_SrcLoc: - return new QueryType(&QuerySession::SrcLocOutput); + if (HasIntrospection) + return new QueryType(&QuerySession::SrcLocOutput); + return new InvalidQuery("'srcloc' output support is not available."); } llvm_unreachable("Invalid output kind"); diff --git a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp --- a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp +++ b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp @@ -9,6 +9,7 @@ #include "QueryParser.h" #include "Query.h" #include "QuerySession.h" +#include "clang/Tooling/NodeIntrospection.h" #include "llvm/LineEditor/LineEditor.h" #include "gtest/gtest.h" @@ -59,6 +60,8 @@ } TEST_F(QueryParserTest, Set) { + + bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport(); QueryRef Q = parse("set"); ASSERT_TRUE(isa(Q)); EXPECT_EQ("expected variable name", cast(Q)->ErrStr); @@ -69,8 +72,13 @@ Q = parse("set output"); ASSERT_TRUE(isa(Q)); - EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''", - cast(Q)->ErrStr); + if (HasIntrospection) + EXPECT_EQ( + "expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', got ''", + cast(Q)->ErrStr); + else + EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''", + cast(Q)->ErrStr); Q = parse("set bind-root true foo"); ASSERT_TRUE(isa(Q)); @@ -78,8 +86,13 @@ Q = parse("set output foo"); ASSERT_TRUE(isa(Q)); - EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'", - cast(Q)->ErrStr); + if (HasIntrospection) + EXPECT_EQ("expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', " + "got 'foo'", + cast(Q)->ErrStr); + else + EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'", + cast(Q)->ErrStr); Q = parse("set output dump"); ASSERT_TRUE(isa(Q)); @@ -217,8 +230,10 @@ EXPECT_EQ("output ", Comps[0].TypedText); EXPECT_EQ("output", Comps[0].DisplayText); + bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport(); + Comps = QueryParser::complete("enable output ", 14, QS); - ASSERT_EQ(5u, Comps.size()); + ASSERT_EQ(HasIntrospection ? 5u : 4u, Comps.size()); EXPECT_EQ("diag ", Comps[0].TypedText); EXPECT_EQ("diag", Comps[0].DisplayText); @@ -226,10 +241,12 @@ EXPECT_EQ("print", Comps[1].DisplayText); EXPECT_EQ("detailed-ast ", Comps[2].TypedText); EXPECT_EQ("detailed-ast", Comps[2].DisplayText); - EXPECT_EQ("srcloc ", Comps[3].TypedText); - EXPECT_EQ("srcloc", Comps[3].DisplayText); - EXPECT_EQ("dump ", Comps[4].TypedText); - EXPECT_EQ("dump", Comps[4].DisplayText); + if (HasIntrospection) { + EXPECT_EQ("srcloc ", Comps[3].TypedText); + EXPECT_EQ("srcloc", Comps[3].DisplayText); + } + EXPECT_EQ("dump ", Comps[HasIntrospection ? 4 : 3].TypedText); + EXPECT_EQ("dump", Comps[HasIntrospection ? 4 : 3].DisplayText); Comps = QueryParser::complete("set traversal ", 14, QS); ASSERT_EQ(2u, Comps.size());