summaryrefslogtreecommitdiffstats
path: root/clang/lib/Tooling/Refactoring/Transformer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Tooling/Refactoring/Transformer.cpp')
-rw-r--r--clang/lib/Tooling/Refactoring/Transformer.cpp102
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());
OpenPOWER on IntegriCloud