tsl-devkit/lsp-server/src/language/symbol/index/location.cppm

85 lines
2.0 KiB
C++

module;
export module lsp.language.symbol:index.location;
import std;
import :types;
import lsp.language.ast;
namespace lsp::language::symbol::index
{
void Location::OnSymbolAdded(const Symbol& symbol)
{
const auto& loc = symbol.selection_range();
entries_.push_back({ loc.start_offset, loc.end_offset, symbol.id() });
needs_sort_ = true;
}
void Location::OnSymbolRemoved(SymbolId id)
{
entries_.erase(
std::remove_if(entries_.begin(), entries_.end(), [id](const Entry& e) { return e.symbol_id == id; }),
entries_.end());
}
void Location::Clear()
{
entries_.clear();
needs_sort_ = false;
}
std::optional<SymbolId> Location::FindSymbolAt(
const ast::Location& location) const
{
EnsureSorted();
std::uint32_t pos = location.start_offset;
auto it =
std::lower_bound(entries_.begin(), entries_.end(), pos, [](const Entry& e, std::uint32_t p) { return e.start < p; });
if (it != entries_.begin())
{
--it;
}
std::optional<SymbolId> result;
std::uint32_t min_span = std::numeric_limits<std::uint32_t>::max();
for (; it != entries_.end() && it->start <= pos; ++it)
{
if (pos >= it->start && pos < it->end)
{
std::uint32_t span = it->end - it->start;
if (span < min_span)
{
min_span = span;
result = it->symbol_id;
}
}
}
return result;
}
bool Location::Entry::operator<(const Entry& other) const
{
if (start != other.start)
{
return start < other.start;
}
return end > other.end;
}
void Location::EnsureSorted() const
{
if (needs_sort_)
{
std::sort(entries_.begin(), entries_.end());
needs_sort_ = false;
}
}
}