diff options
Diffstat (limited to 'clang/lib/Tooling/Syntax/Tokens.cpp')
| -rw-r--r-- | clang/lib/Tooling/Syntax/Tokens.cpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/clang/lib/Tooling/Syntax/Tokens.cpp b/clang/lib/Tooling/Syntax/Tokens.cpp index 234df9cb7182..8a31e776d030 100644 --- a/clang/lib/Tooling/Syntax/Tokens.cpp +++ b/clang/lib/Tooling/Syntax/Tokens.cpp @@ -183,7 +183,39 @@ llvm::StringRef FileRange::text(const SourceManager &SM) const { return Text.substr(Begin, length()); } +void TokenBuffer::indexExpandedTokens() { + // No-op if the index is already created. + if (!ExpandedTokIndex.empty()) + return; + ExpandedTokIndex.reserve(ExpandedTokens.size()); + // Index ExpandedTokens for faster lookups by SourceLocation. + for (size_t I = 0, E = ExpandedTokens.size(); I != E; ++I) { + SourceLocation Loc = ExpandedTokens[I].location(); + if (Loc.isValid()) + ExpandedTokIndex[Loc] = I; + } +} + llvm::ArrayRef<syntax::Token> TokenBuffer::expandedTokens(SourceRange R) const { + if (R.isInvalid()) + return {}; + if (!ExpandedTokIndex.empty()) { + // Quick lookup if `R` is a token range. + // This is a huge win since majority of the users use ranges provided by an + // AST. Ranges in AST are token ranges from expanded token stream. + const auto B = ExpandedTokIndex.find(R.getBegin()); + const auto E = ExpandedTokIndex.find(R.getEnd()); + if (B != ExpandedTokIndex.end() && E != ExpandedTokIndex.end()) { + const Token *L = ExpandedTokens.data() + B->getSecond(); + // Add 1 to End to make a half-open range. + const Token *R = ExpandedTokens.data() + E->getSecond() + 1; + if (L > R) + return {}; + return {L, R}; + } + } + // Slow case. Use `isBeforeInTranslationUnit` to binary search for the + // required range. return getTokensCovering(expandedTokens(), R, *SourceMgr); } |
