[clang] 7d0cdbf - [libTooling] Add `getFileRange` as an alternative to `getRangeForEdit`
Eric Li via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 12 14:44:47 PST 2023
Author: Eric Li
Date: 2023-01-12T17:44:29-05:00
New Revision: 7d0cdbf69edf5b14101d9c11fe9ca4cf5228e81d
URL: https://github.com/llvm/llvm-project/commit/7d0cdbf69edf5b14101d9c11fe9ca4cf5228e81d
DIFF: https://github.com/llvm/llvm-project/commit/7d0cdbf69edf5b14101d9c11fe9ca4cf5228e81d.diff
LOG: [libTooling] Add `getFileRange` as an alternative to `getRangeForEdit`
Add a `getFileRange` function alongside the existing `getRangeForEdit`
as a way to get a contiguous range within a single file (similar to
`getRangeForEdit`) but without the restriction that it cannot be in a
system header.
This can be used where a tool may want to use the range to extract the
source text. In such cases, we don't want to restrict this from
pulling from system headers.
Differential Revision: https://reviews.llvm.org/D141634
Added:
Modified:
clang/include/clang/Tooling/Transformer/SourceCode.h
clang/lib/Tooling/Transformer/SourceCode.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Tooling/Transformer/SourceCode.h b/clang/include/clang/Tooling/Transformer/SourceCode.h
index d95cb9b4ae187..266aae09d27d5 100644
--- a/clang/include/clang/Tooling/Transformer/SourceCode.h
+++ b/clang/include/clang/Tooling/Transformer/SourceCode.h
@@ -112,6 +112,27 @@ getRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context,
return getRangeForEdit(EditRange, Context.getSourceManager(),
Context.getLangOpts(), IncludeMacroExpansion);
}
+
+/// Attempts to resolve the given range to one that starts and ends in a
+/// particular file.
+///
+/// If \c IncludeMacroExpansion is true, a limited set of cases involving source
+/// locations in macro expansions is supported. For example, if we're looking to
+/// get the range of the int literal 3, and we have the following definition:
+/// #define DO_NOTHING(x) x
+/// foo(DO_NOTHING(3))
+/// the returned range will hold the source text `DO_NOTHING(3)`.
+std::optional<CharSourceRange> getFileRange(const CharSourceRange &EditRange,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ bool IncludeMacroExpansion);
+inline std::optional<CharSourceRange>
+getFileRange(const CharSourceRange &EditRange, const ASTContext &Context,
+ bool IncludeMacroExpansion) {
+ return getFileRange(EditRange, Context.getSourceManager(),
+ Context.getLangOpts(), IncludeMacroExpansion);
+}
+
} // namespace tooling
} // namespace clang
#endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H
diff --git a/clang/lib/Tooling/Transformer/SourceCode.cpp b/clang/lib/Tooling/Transformer/SourceCode.cpp
index 008a83cde42c4..262ec3557f7be 100644
--- a/clang/lib/Tooling/Transformer/SourceCode.cpp
+++ b/clang/lib/Tooling/Transformer/SourceCode.cpp
@@ -50,8 +50,9 @@ CharSourceRange clang::tooling::maybeExtendRange(CharSourceRange Range,
return CharSourceRange::getTokenRange(Range.getBegin(), Tok.getLocation());
}
-llvm::Error clang::tooling::validateEditRange(const CharSourceRange &Range,
- const SourceManager &SM) {
+static llvm::Error validateRange(const CharSourceRange &Range,
+ const SourceManager &SM,
+ bool AllowSystemHeaders) {
if (Range.isInvalid())
return llvm::make_error<StringError>(errc::invalid_argument,
"Invalid range");
@@ -60,10 +61,12 @@ llvm::Error clang::tooling::validateEditRange(const CharSourceRange &Range,
return llvm::make_error<StringError>(
errc::invalid_argument, "Range starts or ends in a macro expansion");
- if (SM.isInSystemHeader(Range.getBegin()) ||
- SM.isInSystemHeader(Range.getEnd()))
- return llvm::make_error<StringError>(errc::invalid_argument,
- "Range is in system header");
+ if (!AllowSystemHeaders) {
+ if (SM.isInSystemHeader(Range.getBegin()) ||
+ SM.isInSystemHeader(Range.getEnd()))
+ return llvm::make_error<StringError>(errc::invalid_argument,
+ "Range is in system header");
+ }
std::pair<FileID, unsigned> BeginInfo = SM.getDecomposedLoc(Range.getBegin());
std::pair<FileID, unsigned> EndInfo = SM.getDecomposedLoc(Range.getEnd());
@@ -72,13 +75,18 @@ llvm::Error clang::tooling::validateEditRange(const CharSourceRange &Range,
errc::invalid_argument, "Range begins and ends in
diff erent files");
if (BeginInfo.second > EndInfo.second)
- return llvm::make_error<StringError>(
- errc::invalid_argument, "Range's begin is past its end");
+ return llvm::make_error<StringError>(errc::invalid_argument,
+ "Range's begin is past its end");
return llvm::Error::success();
}
-static bool SpelledInMacroDefinition(SourceLocation Loc,
+llvm::Error clang::tooling::validateEditRange(const CharSourceRange &Range,
+ const SourceManager &SM) {
+ return validateRange(Range, SM, /*AllowSystemHeaders=*/false);
+}
+
+static bool spelledInMacroDefinition(SourceLocation Loc,
const SourceManager &SM) {
while (Loc.isMacroID()) {
const auto &Expansion = SM.getSLocEntry(SM.getFileID(Loc)).getExpansion();
@@ -93,16 +101,17 @@ static bool SpelledInMacroDefinition(SourceLocation Loc,
return false;
}
-std::optional<CharSourceRange> clang::tooling::getRangeForEdit(
- const CharSourceRange &EditRange, const SourceManager &SM,
- const LangOptions &LangOpts, bool IncludeMacroExpansion) {
+static CharSourceRange getRange(const CharSourceRange &EditRange,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ bool IncludeMacroExpansion) {
CharSourceRange Range;
if (IncludeMacroExpansion) {
Range = Lexer::makeFileCharRange(EditRange, SM, LangOpts);
} else {
- if (SpelledInMacroDefinition(EditRange.getBegin(), SM) ||
- SpelledInMacroDefinition(EditRange.getEnd(), SM))
- return std::nullopt;
+ if (spelledInMacroDefinition(EditRange.getBegin(), SM) ||
+ spelledInMacroDefinition(EditRange.getEnd(), SM))
+ return {};
auto B = SM.getSpellingLoc(EditRange.getBegin());
auto E = SM.getSpellingLoc(EditRange.getEnd());
@@ -110,13 +119,32 @@ std::optional<CharSourceRange> clang::tooling::getRangeForEdit(
E = Lexer::getLocForEndOfToken(E, 0, SM, LangOpts);
Range = CharSourceRange::getCharRange(B, E);
}
+ return Range;
+}
+std::optional<CharSourceRange> clang::tooling::getRangeForEdit(
+ const CharSourceRange &EditRange, const SourceManager &SM,
+ const LangOptions &LangOpts, bool IncludeMacroExpansion) {
+ CharSourceRange Range =
+ getRange(EditRange, SM, LangOpts, IncludeMacroExpansion);
bool IsInvalid = llvm::errorToBool(validateEditRange(Range, SM));
if (IsInvalid)
return std::nullopt;
return Range;
}
+std::optional<CharSourceRange> clang::tooling::getFileRange(
+ const CharSourceRange &EditRange, const SourceManager &SM,
+ const LangOptions &LangOpts, bool IncludeMacroExpansion) {
+ CharSourceRange Range =
+ getRange(EditRange, SM, LangOpts, IncludeMacroExpansion);
+ bool IsInvalid =
+ llvm::errorToBool(validateRange(Range, SM, /*AllowSystemHeaders=*/true));
+ if (IsInvalid)
+ return std::nullopt;
+ return Range;
+}
+
static bool startsWithNewline(const SourceManager &SM, const Token &Tok) {
return isVerticalWhitespace(SM.getCharacterData(Tok.getLocation())[0]);
}
More information about the cfe-commits
mailing list