[clang-query] Add check to prevent setting srcloc when no introspection is available.

Checks if introspection support is available set output kind parser.
If it isn't present the auto complete will not suggest `srcloc` and an error query will be reported if a user tries to access it.

Reviewed By: steveire

Differential Revision: https://reviews.llvm.org/D101365
This commit is contained in:
Nathan James 2021-04-28 11:21:34 +01:00
parent 3ea4bc7842
commit 858a9583e1
No known key found for this signature in database
GPG Key ID: CC007AFCDA90AA5F
3 changed files with 43 additions and 20 deletions

View File

@ -149,6 +149,7 @@ struct SetExclusiveOutputQuery : Query {
QS.DiagOutput = false;
QS.DetailedASTOutput = false;
QS.PrintOutput = false;
QS.SrcLocOutput = false;
QS.*Var = true;
return true;
}

View File

@ -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 <set>
@ -104,17 +105,19 @@ QueryRef QueryParser::parseSetBool(bool QuerySession::*Var) {
template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() {
StringRef ValStr;
unsigned OutKind = LexOrCompleteWord<unsigned>(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<unsigned>(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 @@ template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() {
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");

View File

@ -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, Quit) {
}
TEST_F(QueryParserTest, Set) {
bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport();
QueryRef Q = parse("set");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);
@ -69,8 +72,13 @@ TEST_F(QueryParserTest, Set) {
Q = parse("set output");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''",
cast<InvalidQuery>(Q)->ErrStr);
if (HasIntrospection)
EXPECT_EQ(
"expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', got ''",
cast<InvalidQuery>(Q)->ErrStr);
else
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''",
cast<InvalidQuery>(Q)->ErrStr);
Q = parse("set bind-root true foo");
ASSERT_TRUE(isa<InvalidQuery>(Q));
@ -78,8 +86,13 @@ TEST_F(QueryParserTest, Set) {
Q = parse("set output foo");
ASSERT_TRUE(isa<InvalidQuery>(Q));
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'",
cast<InvalidQuery>(Q)->ErrStr);
if (HasIntrospection)
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', "
"got 'foo'",
cast<InvalidQuery>(Q)->ErrStr);
else
EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'",
cast<InvalidQuery>(Q)->ErrStr);
Q = parse("set output dump");
ASSERT_TRUE(isa<SetExclusiveOutputQuery >(Q));
@ -217,8 +230,10 @@ TEST_F(QueryParserTest, Complete) {
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 @@ TEST_F(QueryParserTest, Complete) {
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());