[SourceKit] Use recored #if regions in "active regions" request

* Record each IfConfig clause location info in SourceFile
* Update SILProfiler to handle them
* Update SwiftLangSupport::findActiveRegionsInFile() to use the recorded
  regions instead of walking into AST to find #if regions

rdar://118082146
This commit is contained in:
Rintaro Ishizaki
2024-03-14 06:34:30 +09:00
parent 38ca3cc435
commit 2abddcb260
7 changed files with 188 additions and 127 deletions

View File

@@ -2778,56 +2778,66 @@ SourceFile::getImportAccessLevel(const ModuleDecl *targetModule) const {
return restrictiveImport;
}
SmallVector<CharSourceRange, 2>
IfConfigRangeInfo::getRangesWithoutActiveBody(const SourceManager &SM) const {
SmallVector<CharSourceRange, 2> result;
if (ActiveBodyRange.isValid()) {
// Split the whole range by the active range.
result.emplace_back(SM, WholeRange.getStart(), ActiveBodyRange.getStart());
result.emplace_back(SM, ActiveBodyRange.getEnd(), WholeRange.getEnd());
} else {
// No active body, we just return the whole range.
result.push_back(WholeRange);
CharSourceRange
IfConfigClauseRangeInfo::getDirectiveRange(const SourceManager &SM) const {
return CharSourceRange(SM, DirectiveLoc, BodyLoc);
}
CharSourceRange
IfConfigClauseRangeInfo::getBodyRange(const SourceManager &SM) const {
return CharSourceRange(SM, BodyLoc, EndLoc);
}
CharSourceRange
IfConfigClauseRangeInfo::getWholeRange(const SourceManager &SM) const {
return CharSourceRange(SM, DirectiveLoc, EndLoc);
}
void SourceFile::recordIfConfigClauseRangeInfo(
const IfConfigClauseRangeInfo &range) {
IfConfigClauseRanges.Ranges.push_back(range);
IfConfigClauseRanges.IsSorted = false;
}
ArrayRef<IfConfigClauseRangeInfo> SourceFile::getIfConfigClauseRanges() const {
if (!IfConfigClauseRanges.IsSorted) {
auto &SM = getASTContext().SourceMgr;
// Sort the ranges if we need to.
llvm::sort(
IfConfigClauseRanges.Ranges, [&](const IfConfigClauseRangeInfo &lhs,
const IfConfigClauseRangeInfo &rhs) {
return SM.isBeforeInBuffer(lhs.getStartLoc(), rhs.getStartLoc());
});
// Be defensive and eliminate duplicates in case we've parsed twice.
auto newEnd = llvm::unique(
IfConfigClauseRanges.Ranges, [&](const IfConfigClauseRangeInfo &lhs,
const IfConfigClauseRangeInfo &rhs) {
if (lhs.getStartLoc() != rhs.getStartLoc())
return false;
assert(lhs.getBodyRange(SM) == rhs.getBodyRange(SM) &&
"range changed on a re-parse?");
return true;
});
IfConfigClauseRanges.Ranges.erase(newEnd,
IfConfigClauseRanges.Ranges.end());
IfConfigClauseRanges.IsSorted = true;
}
return result;
return IfConfigClauseRanges.Ranges;
}
void SourceFile::recordIfConfigRangeInfo(IfConfigRangeInfo ranges) {
IfConfigRanges.Ranges.push_back(ranges);
IfConfigRanges.IsSorted = false;
}
ArrayRef<IfConfigRangeInfo>
SourceFile::getIfConfigsWithin(SourceRange outer) const {
ArrayRef<IfConfigClauseRangeInfo>
SourceFile::getIfConfigClausesWithin(SourceRange outer) const {
auto &SM = getASTContext().SourceMgr;
assert(SM.getRangeForBuffer(BufferID).contains(outer.Start) &&
"Range not within this file?");
if (!IfConfigRanges.IsSorted) {
// Sort the ranges if we need to.
llvm::sort(IfConfigRanges.Ranges, [&](IfConfigRangeInfo lhs,
IfConfigRangeInfo rhs) {
return SM.isBeforeInBuffer(lhs.getStartLoc(), rhs.getStartLoc());
});
// Be defensive and eliminate duplicates in case we've parsed twice.
auto newEnd = std::unique(
IfConfigRanges.Ranges.begin(), IfConfigRanges.Ranges.end(),
[&](const IfConfigRangeInfo &lhs, const IfConfigRangeInfo &rhs) {
if (lhs.getWholeRange() != rhs.getWholeRange())
return false;
assert(lhs == rhs && "Active ranges changed on a re-parse?");
return true;
});
IfConfigRanges.Ranges.erase(newEnd, IfConfigRanges.Ranges.end());
IfConfigRanges.IsSorted = true;
}
// First let's find the first #if that is after the outer start loc.
auto ranges = llvm::ArrayRef(IfConfigRanges.Ranges);
auto ranges = getIfConfigClauseRanges();
auto lower = llvm::lower_bound(
ranges, outer.Start, [&](IfConfigRangeInfo range, SourceLoc loc) {
ranges, outer.Start,
[&](const IfConfigClauseRangeInfo &range, SourceLoc loc) {
return SM.isBeforeInBuffer(range.getStartLoc(), loc);
});
if (lower == ranges.end() ||
@@ -2836,7 +2846,8 @@ SourceFile::getIfConfigsWithin(SourceRange outer) const {
}
// Next let's find the first #if that's after the outer end loc.
auto upper = llvm::upper_bound(
ranges, outer.End, [&](SourceLoc loc, IfConfigRangeInfo range) {
ranges, outer.End,
[&](SourceLoc loc, const IfConfigClauseRangeInfo &range) {
return SM.isBeforeInBuffer(loc, range.getStartLoc());
});
return llvm::ArrayRef(lower, upper - lower);