diff options
author | Yitzhak Mandelbaum <yitzhakm@google.com> | 2019-05-22 14:48:19 +0000 |
---|---|---|
committer | Yitzhak Mandelbaum <yitzhakm@google.com> | 2019-05-22 14:48:19 +0000 |
commit | 3ec50e292f35b5792cbb4281ca7380665ff7f195 (patch) | |
tree | b55168076ef67b6c705bf147dbbf3994c67eecaf /clang/lib/Tooling/Refactoring/Transformer.cpp | |
parent | e7230ea7c9dc9b092ee78192d7f32a49bbf28896 (diff) | |
download | bcm5719-llvm-3ec50e292f35b5792cbb4281ca7380665ff7f195.tar.gz bcm5719-llvm-3ec50e292f35b5792cbb4281ca7380665ff7f195.zip |
[LibTooling] Update Transformer to use RangeSelector instead of NodePart enum.
Transformer provides an enum to indicate the range of source text to be edited.
That support is now redundant with the new (and more general) RangeSelector
library, so we remove the custom enum support in favor of supporting any
RangeSelector.
Reviewers: ilya-biryukov
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D62149
llvm-svn: 361392
Diffstat (limited to 'clang/lib/Tooling/Refactoring/Transformer.cpp')
-rw-r--r-- | clang/lib/Tooling/Refactoring/Transformer.cpp | 102 |
1 files changed, 13 insertions, 89 deletions
diff --git a/clang/lib/Tooling/Refactoring/Transformer.cpp b/clang/lib/Tooling/Refactoring/Transformer.cpp index 78506c98a69..bcbe0013107 100644 --- a/clang/lib/Tooling/Refactoring/Transformer.cpp +++ b/clang/lib/Tooling/Refactoring/Transformer.cpp @@ -32,11 +32,7 @@ using ast_matchers::internal::DynTypedMatcher; using ast_type_traits::ASTNodeKind; using ast_type_traits::DynTypedNode; using llvm::Error; -using llvm::Expected; -using llvm::Optional; using llvm::StringError; -using llvm::StringRef; -using llvm::Twine; using MatchResult = MatchFinder::MatchResult; @@ -71,91 +67,12 @@ static bool isOriginMacroBody(const clang::SourceManager &SM, return false; } -static llvm::Error invalidArgumentError(Twine Message) { - return llvm::make_error<StringError>(llvm::errc::invalid_argument, Message); -} - -static llvm::Error typeError(StringRef Id, const ASTNodeKind &Kind, - Twine Message) { - return invalidArgumentError( - Message + " (node id=" + Id + " kind=" + Kind.asStringRef() + ")"); -} - -static llvm::Error missingPropertyError(StringRef Id, Twine Description, - StringRef Property) { - return invalidArgumentError(Description + " requires property '" + Property + - "' (node id=" + Id + ")"); -} - -static Expected<CharSourceRange> -getTargetRange(StringRef Target, const DynTypedNode &Node, ASTNodeKind Kind, - NodePart TargetPart, ASTContext &Context) { - switch (TargetPart) { - case NodePart::Node: { - // For non-expression statements, associate any trailing semicolon with the - // statement text. However, if the target was intended as an expression (as - // indicated by its kind) then we do not associate any trailing semicolon - // with it. We only associate the exact expression text. - if (Node.get<Stmt>() != nullptr) { - auto ExprKind = ASTNodeKind::getFromNodeKind<clang::Expr>(); - if (!ExprKind.isBaseOf(Kind)) - return getExtendedRange(Node, tok::TokenKind::semi, Context); - } - return CharSourceRange::getTokenRange(Node.getSourceRange()); - } - case NodePart::Member: - if (auto *M = Node.get<clang::MemberExpr>()) - return CharSourceRange::getTokenRange( - M->getMemberNameInfo().getSourceRange()); - return typeError(Target, Node.getNodeKind(), - "NodePart::Member applied to non-MemberExpr"); - case NodePart::Name: - if (const auto *D = Node.get<clang::NamedDecl>()) { - if (!D->getDeclName().isIdentifier()) - return missingPropertyError(Target, "NodePart::Name", "identifier"); - SourceLocation L = D->getLocation(); - auto R = CharSourceRange::getTokenRange(L, L); - // Verify that the range covers exactly the name. - // FIXME: extend this code to support cases like `operator +` or - // `foo<int>` for which this range will be too short. Doing so will - // require subcasing `NamedDecl`, because it doesn't provide virtual - // access to the \c DeclarationNameInfo. - if (getText(R, Context) != D->getName()) - return CharSourceRange(); - return R; - } - if (const auto *E = Node.get<clang::DeclRefExpr>()) { - if (!E->getNameInfo().getName().isIdentifier()) - return missingPropertyError(Target, "NodePart::Name", "identifier"); - SourceLocation L = E->getLocation(); - return CharSourceRange::getTokenRange(L, L); - } - if (const auto *I = Node.get<clang::CXXCtorInitializer>()) { - if (!I->isMemberInitializer() && I->isWritten()) - return missingPropertyError(Target, "NodePart::Name", - "explicit member initializer"); - SourceLocation L = I->getMemberLocation(); - return CharSourceRange::getTokenRange(L, L); - } - return typeError( - Target, Node.getNodeKind(), - "NodePart::Name applied to neither DeclRefExpr, NamedDecl nor " - "CXXCtorInitializer"); - } - llvm_unreachable("Unexpected case in NodePart type."); -} - Expected<SmallVector<tooling::detail::Transformation, 1>> tooling::detail::translateEdits(const MatchResult &Result, llvm::ArrayRef<ASTEdit> Edits) { - SmallVector<Transformation, 1> Transformations; - auto &NodesMap = Result.Nodes.getMap(); + SmallVector<tooling::detail::Transformation, 1> Transformations; for (const auto &Edit : Edits) { - auto It = NodesMap.find(Edit.Target); - assert(It != NodesMap.end() && "Edit target must be bound in the match."); - - Expected<CharSourceRange> Range = getTargetRange( - Edit.Target, It->second, Edit.Kind, Edit.Part, *Result.Context); + Expected<CharSourceRange> Range = Edit.TargetRange(Result); if (!Range) return Range.takeError(); if (Range->isInvalid() || @@ -164,7 +81,7 @@ tooling::detail::translateEdits(const MatchResult &Result, auto Replacement = Edit.Replacement(Result); if (!Replacement) return Replacement.takeError(); - Transformation T; + tooling::detail::Transformation T; T.Range = *Range; T.Replacement = std::move(*Replacement); Transformations.push_back(std::move(T)); @@ -172,6 +89,13 @@ tooling::detail::translateEdits(const MatchResult &Result, return Transformations; } +ASTEdit tooling::change(RangeSelector S, TextGenerator Replacement) { + ASTEdit E; + E.TargetRange = std::move(S); + E.Replacement = std::move(Replacement); + return E; +} + RewriteRule tooling::makeRule(DynTypedMatcher M, SmallVector<ASTEdit, 1> Edits) { return RewriteRule{ @@ -255,7 +179,7 @@ DynTypedMatcher tooling::detail::buildMatcher(const RewriteRule &Rule) { DynTypedMatcher M = joinCaseMatchers(Rule); M.setAllowBind(true); // `tryBind` is guaranteed to succeed, because `AllowBind` was set to true. - return *M.tryBind(RewriteRule::RootId); + return *M.tryBind(RewriteRule::RootID); } // Finds the case that was "selected" -- that is, whose matcher triggered the @@ -275,7 +199,7 @@ tooling::detail::findSelectedCase(const MatchResult &Result, llvm_unreachable("No tag found for this rule."); } -constexpr llvm::StringLiteral RewriteRule::RootId; +constexpr llvm::StringLiteral RewriteRule::RootID; void Transformer::registerMatchers(MatchFinder *MatchFinder) { MatchFinder->addDynamicMatcher(tooling::detail::buildMatcher(Rule), this); @@ -287,7 +211,7 @@ void Transformer::run(const MatchResult &Result) { // Verify the existence and validity of the AST node that roots this rule. auto &NodesMap = Result.Nodes.getMap(); - auto Root = NodesMap.find(RewriteRule::RootId); + auto Root = NodesMap.find(RewriteRule::RootID); assert(Root != NodesMap.end() && "Transformation failed: missing root node."); SourceLocation RootLoc = Result.SourceManager->getExpansionLoc( Root->second.getSourceRange().getBegin()); |