mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-27 10:02:03 +00:00
$ccls/publishSemanticHighlighting: use pair<int,int> in place of lsRange
This commit is contained in:
parent
0a304096df
commit
7d1d4b410b
@ -534,11 +534,13 @@ public:
|
|||||||
off |= 1u << 31;
|
off |= 1u << 31;
|
||||||
Loc = SourceLocation::getFromRawEncoding(off);
|
Loc = SourceLocation::getFromRawEncoding(off);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
FileID LocFID;
|
||||||
#endif
|
#endif
|
||||||
SourceLocation Spell = SM.getSpellingLoc(Loc);
|
SourceLocation Spell = SM.getSpellingLoc(Loc);
|
||||||
Loc = SM.getFileLoc(Loc);
|
Loc = SM.getFileLoc(Loc);
|
||||||
Range loc = FromTokenRange(SM, Lang, SourceRange(Loc, Loc));
|
Range loc = FromTokenRange(SM, Lang, SourceRange(Loc, Loc));
|
||||||
FileID LocFID = SM.getFileID(Loc);
|
LocFID = SM.getFileID(Loc);
|
||||||
const FileEntry *FE = SM.getFileEntryForID(LocFID);
|
const FileEntry *FE = SM.getFileEntryForID(LocFID);
|
||||||
if (!FE) {
|
if (!FE) {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
|
||||||
#include "log.hh"
|
#include "log.hh"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "pipeline.hh"
|
|
||||||
using namespace ccls;
|
using namespace ccls;
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
@ -30,8 +30,8 @@ struct ScanLineEvent {
|
|||||||
lsPosition pos;
|
lsPosition pos;
|
||||||
lsPosition end_pos; // Second key when there is a tie for insertion events.
|
lsPosition end_pos; // Second key when there is a tie for insertion events.
|
||||||
int id;
|
int id;
|
||||||
Out_CclsPublishSemanticHighlighting::Symbol* symbol;
|
Out_CclsPublishSemanticHighlighting::Symbol *symbol;
|
||||||
bool operator<(const ScanLineEvent& other) const {
|
bool operator<(const ScanLineEvent &other) const {
|
||||||
// See the comments below when insertion/deletion events are inserted.
|
// See the comments below when insertion/deletion events are inserted.
|
||||||
if (!(pos == other.pos))
|
if (!(pos == other.pos))
|
||||||
return pos < other.pos;
|
return pos < other.pos;
|
||||||
@ -45,14 +45,12 @@ struct ScanLineEvent {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
SemanticHighlightSymbolCache::Entry::Entry(
|
SemanticHighlightSymbolCache::Entry::Entry(
|
||||||
SemanticHighlightSymbolCache* all_caches,
|
SemanticHighlightSymbolCache *all_caches, const std::string &path)
|
||||||
const std::string& path)
|
|
||||||
: all_caches_(all_caches), path(path) {}
|
: all_caches_(all_caches), path(path) {}
|
||||||
|
|
||||||
std::optional<int> SemanticHighlightSymbolCache::Entry::TryGetStableId(
|
std::optional<int> SemanticHighlightSymbolCache::Entry::TryGetStableId(
|
||||||
SymbolKind kind,
|
SymbolKind kind, const std::string &detailed_name) {
|
||||||
const std::string& detailed_name) {
|
TNameToId *map = GetMapForSymbol_(kind);
|
||||||
TNameToId* map = GetMapForSymbol_(kind);
|
|
||||||
auto it = map->find(detailed_name);
|
auto it = map->find(detailed_name);
|
||||||
if (it != map->end())
|
if (it != map->end())
|
||||||
return it->second;
|
return it->second;
|
||||||
@ -61,14 +59,13 @@ std::optional<int> SemanticHighlightSymbolCache::Entry::TryGetStableId(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int SemanticHighlightSymbolCache::Entry::GetStableId(
|
int SemanticHighlightSymbolCache::Entry::GetStableId(
|
||||||
SymbolKind kind,
|
SymbolKind kind, const std::string &detailed_name) {
|
||||||
const std::string& detailed_name) {
|
|
||||||
std::optional<int> id = TryGetStableId(kind, detailed_name);
|
std::optional<int> id = TryGetStableId(kind, detailed_name);
|
||||||
if (id)
|
if (id)
|
||||||
return *id;
|
return *id;
|
||||||
|
|
||||||
// Create a new id. First try to find a key in another map.
|
// Create a new id. First try to find a key in another map.
|
||||||
all_caches_->cache_.IterateValues([&](const std::shared_ptr<Entry>& entry) {
|
all_caches_->cache_.IterateValues([&](const std::shared_ptr<Entry> &entry) {
|
||||||
std::optional<int> other_id = entry->TryGetStableId(kind, detailed_name);
|
std::optional<int> other_id = entry->TryGetStableId(kind, detailed_name);
|
||||||
if (other_id) {
|
if (other_id) {
|
||||||
id = other_id;
|
id = other_id;
|
||||||
@ -78,13 +75,13 @@ int SemanticHighlightSymbolCache::Entry::GetStableId(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Create a new id.
|
// Create a new id.
|
||||||
TNameToId* map = GetMapForSymbol_(kind);
|
TNameToId *map = GetMapForSymbol_(kind);
|
||||||
if (!id)
|
if (!id)
|
||||||
id = all_caches_->next_stable_id_++;
|
id = all_caches_->next_stable_id_++;
|
||||||
return (*map)[detailed_name] = *id;
|
return (*map)[detailed_name] = *id;
|
||||||
}
|
}
|
||||||
|
|
||||||
SemanticHighlightSymbolCache::Entry::TNameToId*
|
SemanticHighlightSymbolCache::Entry::TNameToId *
|
||||||
SemanticHighlightSymbolCache::Entry::GetMapForSymbol_(SymbolKind kind) {
|
SemanticHighlightSymbolCache::Entry::GetMapForSymbol_(SymbolKind kind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case SymbolKind::Type:
|
case SymbolKind::Type:
|
||||||
@ -110,7 +107,7 @@ void SemanticHighlightSymbolCache::Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SemanticHighlightSymbolCache::Entry>
|
std::shared_ptr<SemanticHighlightSymbolCache::Entry>
|
||||||
SemanticHighlightSymbolCache::GetCacheForFile(const std::string& path) {
|
SemanticHighlightSymbolCache::GetCacheForFile(const std::string &path) {
|
||||||
return cache_.Get(
|
return cache_.Get(
|
||||||
path, [&, this]() { return std::make_shared<Entry>(this, path); });
|
path, [&, this]() { return std::make_shared<Entry>(this, path); });
|
||||||
}
|
}
|
||||||
@ -119,24 +116,21 @@ MessageHandler::MessageHandler() {
|
|||||||
// Dynamically allocate |message_handlers|, otherwise there will be static
|
// Dynamically allocate |message_handlers|, otherwise there will be static
|
||||||
// initialization order races.
|
// initialization order races.
|
||||||
if (!message_handlers)
|
if (!message_handlers)
|
||||||
message_handlers = new std::vector<MessageHandler*>();
|
message_handlers = new std::vector<MessageHandler *>();
|
||||||
message_handlers->push_back(this);
|
message_handlers->push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
std::vector<MessageHandler*>* MessageHandler::message_handlers = nullptr;
|
std::vector<MessageHandler *> *MessageHandler::message_handlers = nullptr;
|
||||||
|
|
||||||
bool FindFileOrFail(DB* db,
|
bool FindFileOrFail(DB *db, Project *project, std::optional<lsRequestId> id,
|
||||||
Project* project,
|
const std::string &absolute_path,
|
||||||
std::optional<lsRequestId> id,
|
QueryFile **out_query_file, int *out_file_id) {
|
||||||
const std::string& absolute_path,
|
|
||||||
QueryFile** out_query_file,
|
|
||||||
int* out_file_id) {
|
|
||||||
*out_query_file = nullptr;
|
*out_query_file = nullptr;
|
||||||
|
|
||||||
auto it = db->name2file_id.find(LowerPathIfInsensitive(absolute_path));
|
auto it = db->name2file_id.find(LowerPathIfInsensitive(absolute_path));
|
||||||
if (it != db->name2file_id.end()) {
|
if (it != db->name2file_id.end()) {
|
||||||
QueryFile& file = db->files[it->second];
|
QueryFile &file = db->files[it->second];
|
||||||
if (file.def) {
|
if (file.def) {
|
||||||
*out_query_file = &file;
|
*out_query_file = &file;
|
||||||
if (out_file_id)
|
if (out_file_id)
|
||||||
@ -187,10 +181,9 @@ void EmitSkippedRanges(WorkingFile *working_file,
|
|||||||
pipeline::WriteStdout(kMethodType_CclsPublishSkippedRanges, out);
|
pipeline::WriteStdout(kMethodType_CclsPublishSkippedRanges, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSemanticHighlighting(DB* db,
|
void EmitSemanticHighlighting(DB *db,
|
||||||
SemanticHighlightSymbolCache* semantic_cache,
|
SemanticHighlightSymbolCache *semantic_cache,
|
||||||
WorkingFile* wfile,
|
WorkingFile *wfile, QueryFile *file) {
|
||||||
QueryFile* file) {
|
|
||||||
assert(file->def);
|
assert(file->def);
|
||||||
if (wfile->buffer_content.size() > g_config->largeFileSize ||
|
if (wfile->buffer_content.size() > g_config->largeFileSize ||
|
||||||
!semantic_cache->match_->IsMatch(file->def->path))
|
!semantic_cache->match_->IsMatch(file->def->path))
|
||||||
@ -209,8 +202,8 @@ void EmitSemanticHighlighting(DB* db,
|
|||||||
// This switch statement also filters out symbols that are not highlighted.
|
// This switch statement also filters out symbols that are not highlighted.
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Func: {
|
case SymbolKind::Func: {
|
||||||
const QueryFunc& func = db->GetFunc(sym);
|
const QueryFunc &func = db->GetFunc(sym);
|
||||||
const QueryFunc::Def* def = func.AnyDef();
|
const QueryFunc::Def *def = func.AnyDef();
|
||||||
if (!def)
|
if (!def)
|
||||||
continue; // applies to for loop
|
continue; // applies to for loop
|
||||||
if (def->spell)
|
if (def->spell)
|
||||||
@ -251,7 +244,7 @@ void EmitSemanticHighlighting(DB* db,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type:
|
case SymbolKind::Type:
|
||||||
for (auto& def : db->GetType(sym).def) {
|
for (auto &def : db->GetType(sym).def) {
|
||||||
kind = def.kind;
|
kind = def.kind;
|
||||||
detailed_name = def.detailed_name;
|
detailed_name = def.detailed_name;
|
||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
@ -261,8 +254,8 @@ void EmitSemanticHighlighting(DB* db,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var: {
|
case SymbolKind::Var: {
|
||||||
const QueryVar& var = db->GetVar(sym);
|
const QueryVar &var = db->GetVar(sym);
|
||||||
for (auto& def : var.def) {
|
for (auto &def : var.def) {
|
||||||
kind = def.kind;
|
kind = def.kind;
|
||||||
storage = def.storage;
|
storage = def.storage;
|
||||||
detailed_name = def.detailed_name;
|
detailed_name = def.detailed_name;
|
||||||
@ -287,7 +280,7 @@ void EmitSemanticHighlighting(DB* db,
|
|||||||
if (loc) {
|
if (loc) {
|
||||||
auto it = grouped_symbols.find(sym);
|
auto it = grouped_symbols.find(sym);
|
||||||
if (it != grouped_symbols.end()) {
|
if (it != grouped_symbols.end()) {
|
||||||
it->second.ranges.push_back(*loc);
|
it->second.lsRanges.push_back(*loc);
|
||||||
} else {
|
} else {
|
||||||
Out_CclsPublishSemanticHighlighting::Symbol symbol;
|
Out_CclsPublishSemanticHighlighting::Symbol symbol;
|
||||||
symbol.stableId = semantic_cache_for_file->GetStableId(
|
symbol.stableId = semantic_cache_for_file->GetStableId(
|
||||||
@ -295,7 +288,7 @@ void EmitSemanticHighlighting(DB* db,
|
|||||||
symbol.parentKind = parent_kind;
|
symbol.parentKind = parent_kind;
|
||||||
symbol.kind = kind;
|
symbol.kind = kind;
|
||||||
symbol.storage = storage;
|
symbol.storage = storage;
|
||||||
symbol.ranges.push_back(*loc);
|
symbol.lsRanges.push_back(*loc);
|
||||||
grouped_symbols[sym] = symbol;
|
grouped_symbols[sym] = symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,9 +297,9 @@ void EmitSemanticHighlighting(DB* db,
|
|||||||
// Make ranges non-overlapping using a scan line algorithm.
|
// Make ranges non-overlapping using a scan line algorithm.
|
||||||
std::vector<ScanLineEvent> events;
|
std::vector<ScanLineEvent> events;
|
||||||
int id = 0;
|
int id = 0;
|
||||||
for (auto& entry : grouped_symbols) {
|
for (auto &entry : grouped_symbols) {
|
||||||
Out_CclsPublishSemanticHighlighting::Symbol& symbol = entry.second;
|
Out_CclsPublishSemanticHighlighting::Symbol &symbol = entry.second;
|
||||||
for (auto& loc : symbol.ranges) {
|
for (auto &loc : symbol.lsRanges) {
|
||||||
// For ranges sharing the same start point, the one with leftmost end
|
// For ranges sharing the same start point, the one with leftmost end
|
||||||
// point comes first.
|
// point comes first.
|
||||||
events.push_back({loc.start, loc.end, id, &symbol});
|
events.push_back({loc.start, loc.end, id, &symbol});
|
||||||
@ -316,7 +309,7 @@ void EmitSemanticHighlighting(DB* db,
|
|||||||
events.push_back({loc.end, loc.end, ~id, &symbol});
|
events.push_back({loc.end, loc.end, ~id, &symbol});
|
||||||
id++;
|
id++;
|
||||||
}
|
}
|
||||||
symbol.ranges.clear();
|
symbol.lsRanges.clear();
|
||||||
}
|
}
|
||||||
std::sort(events.begin(), events.end());
|
std::sort(events.begin(), events.end());
|
||||||
|
|
||||||
@ -332,19 +325,54 @@ void EmitSemanticHighlighting(DB* db,
|
|||||||
// Attribute range [events[i-1].pos, events[i].pos) to events[top-1].symbol
|
// Attribute range [events[i-1].pos, events[i].pos) to events[top-1].symbol
|
||||||
// .
|
// .
|
||||||
if (top && !(events[i - 1].pos == events[i].pos))
|
if (top && !(events[i - 1].pos == events[i].pos))
|
||||||
events[top - 1].symbol->ranges.push_back(
|
events[top - 1].symbol->lsRanges.push_back(
|
||||||
lsRange{events[i - 1].pos, events[i].pos});
|
{events[i - 1].pos, events[i].pos});
|
||||||
if (events[i].id >= 0)
|
if (events[i].id >= 0)
|
||||||
events[top++] = events[i];
|
events[top++] = events[i];
|
||||||
else
|
else
|
||||||
deleted[~events[i].id] = 1;
|
deleted[~events[i].id] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish.
|
|
||||||
Out_CclsPublishSemanticHighlighting out;
|
Out_CclsPublishSemanticHighlighting out;
|
||||||
out.params.uri = lsDocumentUri::FromPath(wfile->filename);
|
out.params.uri = lsDocumentUri::FromPath(wfile->filename);
|
||||||
for (auto& entry : grouped_symbols)
|
// Transform lsRange into pair<int, int> (offset pairs)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<lsRange, Out_CclsPublishSemanticHighlighting::Symbol *>>
|
||||||
|
scratch;
|
||||||
|
for (auto &entry : grouped_symbols)
|
||||||
|
for (auto &range : entry.second.lsRanges)
|
||||||
|
scratch.emplace_back(range, &entry.second);
|
||||||
|
std::sort(scratch.begin(), scratch.end(),
|
||||||
|
[](auto &l, auto &r) { return l.first.start < r.first.start; });
|
||||||
|
const auto &buf = wfile->buffer_content;
|
||||||
|
int l = 0, c = 0, i = 0;
|
||||||
|
auto mov = [&](int line, int col) {
|
||||||
|
if (l < line)
|
||||||
|
c = 0;
|
||||||
|
for (; l < line && i < buf.size(); i++)
|
||||||
|
if (buf[i] == '\n')
|
||||||
|
l++;
|
||||||
|
if (l < line) return true;
|
||||||
|
for (; c < col && i < buf.size(); c++)
|
||||||
|
if (uint8_t(buf[i++]) >= 128)
|
||||||
|
// Skip 0b10xxxxxx
|
||||||
|
while (i < buf.size() && uint8_t(buf[i]) >= 128 && uint8_t(buf[i]) < 192)
|
||||||
|
i++;
|
||||||
|
return c < col;
|
||||||
|
};
|
||||||
|
for (auto &entry : scratch) {
|
||||||
|
lsRange &r = entry.first;
|
||||||
|
if (mov(r.start.line, r.start.character))
|
||||||
|
continue;
|
||||||
|
int beg = i;
|
||||||
|
if (mov(r.end.line, r.end.character))
|
||||||
|
continue;
|
||||||
|
entry.second->ranges.emplace_back(beg, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &entry : grouped_symbols)
|
||||||
if (entry.second.ranges.size())
|
if (entry.second.ranges.size())
|
||||||
out.params.symbols.push_back(entry.second);
|
out.params.symbols.push_back(std::move(entry.second));
|
||||||
pipeline::WriteStdout(kMethodType_CclsPublishSemanticHighlighting, out);
|
pipeline::WriteStdout(kMethodType_CclsPublishSemanticHighlighting, out);
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,10 @@ struct Out_CclsPublishSemanticHighlighting
|
|||||||
lsSymbolKind parentKind;
|
lsSymbolKind parentKind;
|
||||||
lsSymbolKind kind;
|
lsSymbolKind kind;
|
||||||
clang::StorageClass storage;
|
clang::StorageClass storage;
|
||||||
std::vector<lsRange> ranges;
|
std::vector<std::pair<int, int>> ranges;
|
||||||
|
|
||||||
|
// `lsRanges` is used to compute `ranges`.
|
||||||
|
std::vector<lsRange> lsRanges;
|
||||||
};
|
};
|
||||||
struct Params {
|
struct Params {
|
||||||
lsDocumentUri uri;
|
lsDocumentUri uri;
|
||||||
|
Loading…
Reference in New Issue
Block a user