From 858a9583e1fed24aa57e5f2769f4117883264ceb Mon Sep 17 00:00:00 2001 From: Nathan James Date: Wed, 28 Apr 2021 11:21:34 +0100 Subject: [PATCH] [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 --- clang-tools-extra/clang-query/Query.h | 1 + clang-tools-extra/clang-query/QueryParser.cpp | 27 ++++++++------ .../unittests/clang-query/QueryParserTest.cpp | 35 ++++++++++++++----- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/clang-tools-extra/clang-query/Query.h b/clang-tools-extra/clang-query/Query.h index 38be29101c96..f96bf196a642 100644 --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -149,6 +149,7 @@ struct SetExclusiveOutputQuery : Query { 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 index b444162cfc0a..b80ad04726bc 100644 --- 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 @@ QueryRef QueryParser::parseSetBool(bool QuerySession::*Var) { 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 @@ template 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"); diff --git a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp index 713a6c23848a..06b0d7b36590 100644 --- 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, Quit) { } 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 @@ TEST_F(QueryParserTest, Set) { 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 @@ TEST_F(QueryParserTest, Set) { 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 @@ 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());