35 bool afterBegin = (line > beginLine) ||
36 (line == beginLine && column >= beginColumn);
39 bool beforeEnd = (line < endLine) || (line == endLine && column <= endColumn);
41 return afterBegin && beforeEnd;
45 if (beginLine != other.beginLine) {
46 return beginLine < other.beginLine;
48 return beginColumn < other.beginColumn;
56 intervals_.push_back(interval);
65 std::sort(intervals_.begin(), intervals_.end());
70 unsigned column)
const {
71 std::vector<AstViewNode *> results;
76 for (
const Interval &interval : intervals_) {
78 if (interval.beginLine > line ||
79 (interval.beginLine == line && interval.beginColumn > column)) {
84 if (interval.contains(line, column)) {
85 results.push_back(interval.node);
90 std::sort(results.begin(), results.end(),
92 return getDepth(a) > getDepth(b);
101 unsigned endColumn)
const {
103 Interval searchKey{beginLine, beginColumn, 0, 0,
nullptr};
104 auto it = std::lower_bound(intervals_.begin(), intervals_.end(), searchKey);
106 for (; it != intervals_.end(); ++it) {
108 if (it->beginLine > endLine ||
109 (it->beginLine == endLine && it->beginColumn > endColumn)) {
114 bool startsInRange = it->beginLine > beginLine ||
115 (it->beginLine == beginLine && it->beginColumn >= beginColumn);
116 bool endsInRange = it->endLine < endLine ||
117 (it->endLine == endLine && it->endColumn <= endColumn);
119 if (startsInRange && endsInRange) {
127unsigned IntervalTree::getDepth(
AstViewNode *node)
const {
133 AstViewNode *current = node;
134 while (current->getParent()) {
136 current = current->getParent();
151 FileID fileId = range.begin().fileID();
159 Interval interval{range.begin().line(), range.begin().column(),
160 range.end().line(), range.end().column(), node};
163 trees_[fileId].insert(interval);
168 for (
auto &[fileId, tree] : trees_) {
175 unsigned column)
const {
176 auto it = trees_.find(fileId);
177 if (it == trees_.end()) {
181 return it->second.query(line, column);
185 FileID fileId,
unsigned beginLine,
unsigned beginColumn,
unsigned endLine,
186 unsigned endColumn)
const {
187 auto it = trees_.find(fileId);
188 if (it == trees_.end()) {
192 return it->second.queryFirstContained(beginLine, beginColumn, endLine,
197 std::size_t total = 0;
198 for (
const auto &[fileId, tree] : trees_) {
199 total += tree.size();
205 return trees_.find(fileId) != trees_.end();
AST data structures and memory management.
std::size_t FileID
Type-safe identifier for registered files. 0 is reserved for invalid.
Source-to-AST node lookup index.
Represents node in AST tree hierarchy.
const SourceRange & getSourceRange() const
Get source range (delegates to data node).
static constexpr FileID InvalidFileID
Reserved invalid FileID.
AstViewNode * queryFirstContained(unsigned beginLine, unsigned beginColumn, unsigned endLine, unsigned endColumn) const
Find first interval fully contained within a range.
void finalize()
Sort intervals by start position (call once after all inserts).
std::vector< AstViewNode * > query(unsigned line, unsigned column) const
Find all intervals containing a point.
void insert(Interval interval)
Add interval to collection (not sorted yet).
void finalize()
Finalize all interval trees (call after all nodes added).
void addNode(AstViewNode *node)
Add node to index.
std::vector< AstViewNode * > getNodesAt(FileID fileId, unsigned line, unsigned column) const
Query nodes at specific source position.
bool hasFile(FileID fileId) const
Check whether the current TU AST contains any indexed nodes for a file.
std::size_t getTotalIntervals() const
Get total number of intervals across all files.
AstViewNode * getFirstNodeContainedInRange(FileID fileId, unsigned beginLine, unsigned beginColumn, unsigned endLine, unsigned endColumn) const
Query first node fully contained within a range.
Represents a span of source code (begin to end).
Represents an interval in source code with associated AST node.
bool operator<(const Interval &other) const
Compare intervals by start position for sorting.
bool contains(unsigned line, unsigned column) const
Check if interval contains a point.