-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[clang][transformer] Add merge range-selector for selecting the merge of two ranges.
#169560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -178,6 +178,56 @@ RangeSelector transformer::encloseNodes(std::string BeginID, | |
| return transformer::enclose(node(std::move(BeginID)), node(std::move(EndID))); | ||
| } | ||
|
|
||
| RangeSelector transformer::merge(RangeSelector First, RangeSelector Second) { | ||
| return [First, | ||
| Second](const MatchResult &Result) -> Expected<CharSourceRange> { | ||
| Expected<CharSourceRange> FirstRange = First(Result); | ||
| if (!FirstRange) | ||
| return FirstRange.takeError(); | ||
| Expected<CharSourceRange> SecondRange = Second(Result); | ||
| if (!SecondRange) | ||
| return SecondRange.takeError(); | ||
| // Result begin loc is the minimum of the begin locs of the two ranges. | ||
| SourceLocation B = FirstRange->getBegin() < SecondRange->getBegin() | ||
| ? FirstRange->getBegin() | ||
| : SecondRange->getBegin(); | ||
| if (FirstRange->isTokenRange() && SecondRange->isTokenRange()) { | ||
| // Both ranges are token ranges. Just take the maximum of their end locs. | ||
| SourceLocation E = FirstRange->getEnd() > SecondRange->getEnd() | ||
| ? FirstRange->getEnd() | ||
| : SecondRange->getEnd(); | ||
| return CharSourceRange::getTokenRange(B, E); | ||
| } | ||
| SourceLocation FirstE = FirstRange->getEnd(); | ||
| if (FirstRange->isTokenRange()) { | ||
| // The end of the first range is a token. Need to resolve the token to a | ||
| // char range. | ||
| CharSourceRange EndRange = Lexer::makeFileCharRange( | ||
|
||
| CharSourceRange::getTokenRange(FirstRange->getEnd()), | ||
| *Result.SourceManager, Result.Context->getLangOpts()); | ||
| if (EndRange.isInvalid()) | ||
| return invalidArgumentError( | ||
| "merge: can't resolve first token range to valid source range"); | ||
| FirstE = EndRange.getEnd(); | ||
| } | ||
| SourceLocation SecondE = SecondRange->getEnd(); | ||
| if (SecondRange->isTokenRange()) { | ||
| // The end of the second range is a token. Need to resolve the token to a | ||
| // char range. | ||
| CharSourceRange EndRange = Lexer::makeFileCharRange( | ||
| CharSourceRange::getTokenRange(SecondRange->getEnd()), | ||
| *Result.SourceManager, Result.Context->getLangOpts()); | ||
| if (EndRange.isInvalid()) | ||
| return invalidArgumentError( | ||
| "merge: can't resolve second token range to valid source range"); | ||
| SecondE = EndRange.getEnd(); | ||
| } | ||
| // Result end loc is the maximum of the end locs of the two ranges. | ||
| SourceLocation E = FirstE > SecondE ? FirstE : SecondE; | ||
| return CharSourceRange::getCharRange(B, E); | ||
| }; | ||
| } | ||
|
|
||
| RangeSelector transformer::member(std::string ID) { | ||
| return [ID](const MatchResult &Result) -> Expected<CharSourceRange> { | ||
| Expected<DynTypedNode> Node = getNode(Result.Nodes, ID); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we generally don't compare source ranges when we care about semantic details. Instead, we use APIs like isBeforeInTranslationUnit. I don't remember the subtleties offhand, but that's what we use e.g. on line 169 and should be a good start at least. I would recommend you look at the declaration and implementation of makeFileCharRange to get a sense for the subtleties involved here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Fixed.