[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