Implement textDocument/documentHighlight

This commit is contained in:
Jacob Dufault 2017-04-13 23:43:50 -07:00
parent 20bf746ee9
commit 71d1b1ffc6
7 changed files with 99 additions and 2 deletions

View File

@ -538,6 +538,7 @@ std::unique_ptr<IpcMessageQueue> BuildIpcMessageQueue(const std::string& name, s
RegisterId<Ipc_TextDocumentDidSave>(ipc.get());
RegisterId<Ipc_TextDocumentComplete>(ipc.get());
RegisterId<Ipc_TextDocumentDefinition>(ipc.get());
RegisterId<Ipc_TextDocumentDocumentHighlight>(ipc.get());
RegisterId<Ipc_TextDocumentHover>(ipc.get());
RegisterId<Ipc_TextDocumentReferences>(ipc.get());
RegisterId<Ipc_TextDocumentDocumentSymbol>(ipc.get());
@ -561,6 +562,7 @@ void RegisterMessageTypes() {
MessageRegistry::instance()->Register<Ipc_TextDocumentDidSave>();
MessageRegistry::instance()->Register<Ipc_TextDocumentComplete>();
MessageRegistry::instance()->Register<Ipc_TextDocumentDefinition>();
MessageRegistry::instance()->Register<Ipc_TextDocumentDocumentHighlight>();
MessageRegistry::instance()->Register<Ipc_TextDocumentHover>();
MessageRegistry::instance()->Register<Ipc_TextDocumentReferences>();
MessageRegistry::instance()->Register<Ipc_TextDocumentDocumentSymbol>();
@ -918,6 +920,49 @@ void QueryDbMainLoop(
break;
}
case IpcId::TextDocumentDocumentHighlight: {
auto msg = static_cast<Ipc_TextDocumentDocumentHighlight*>(message.get());
QueryFileId file_id;
QueryableFile* file = FindFile(db, msg->params.textDocument.uri.GetPath(), &file_id);
if (!file) {
std::cerr << "Unable to find file " << msg->params.textDocument.uri.GetPath() << std::endl;
break;
}
Out_TextDocumentDocumentHighlight response;
response.id = msg->id;
// TODO: consider refactoring into FindSymbolsAtLocation(file);
int target_line = msg->params.position.line + 1;
int target_column = msg->params.position.character + 1;
for (const SymbolRef& ref : file->def.all_symbols) {
if (ref.loc.range.start.line >= target_line && ref.loc.range.end.line <= target_line &&
ref.loc.range.start.column <= target_column && ref.loc.range.end.column >= target_column) {
// Found symbol. Return references to highlight.
std::vector<QueryableLocation> uses = GetUsesOfSymbol(db, ref.idx);
response.result.reserve(uses.size());
for (const QueryableLocation& use : uses) {
if (use.path != file_id)
continue;
optional<lsLocation> ls_location = GetLsLocation(db, working_files, use);
if (!ls_location)
continue;
lsDocumentHighlight highlight;
highlight.kind = lsDocumentHighlightKind::Text;
highlight.range = ls_location->range;
response.result.push_back(highlight);
}
break;
}
}
SendOutMessageToClient(language_client, response);
break;
}
case IpcId::TextDocumentHover: {
auto msg = static_cast<Ipc_TextDocumentHover*>(message.get());
@ -929,13 +974,14 @@ void QueryDbMainLoop(
Out_TextDocumentHover response;
response.id = msg->id;
// TODO: consider refactoring into FindSymbolsAtLocation(file);
int target_line = msg->params.position.line + 1;
int target_column = msg->params.position.character + 1;
for (const SymbolRef& ref : file->def.all_symbols) {
if (ref.loc.range.start.line >= target_line && ref.loc.range.end.line <= target_line &&
ref.loc.range.start.column <= target_column && ref.loc.range.end.column >= target_column) {
// Found symbol. Return references.
// Found symbol. Return hover.
optional<lsRange> ls_range = GetLsRange(working_files->GetFileByFilename(file->def.usr), ref.loc.range);
if (!ls_range)
continue;
@ -1282,8 +1328,8 @@ void LanguageServerStdinLoop(IpcMessageQueue* ipc) {
response.result.capabilities.codeLensProvider->resolveProvider = false;
response.result.capabilities.definitionProvider = true;
response.result.capabilities.documentHighlightProvider = true;
response.result.capabilities.hoverProvider = true;
response.result.capabilities.referencesProvider = true;
response.result.capabilities.documentSymbolProvider = true;
@ -1310,6 +1356,7 @@ void LanguageServerStdinLoop(IpcMessageQueue* ipc) {
case IpcId::TextDocumentDidSave:
case IpcId::TextDocumentCompletion:
case IpcId::TextDocumentDefinition:
case IpcId::TextDocumentDocumentHighlight:
case IpcId::TextDocumentHover:
case IpcId::TextDocumentReferences:
case IpcId::TextDocumentDocumentSymbol:

View File

@ -50,6 +50,10 @@ bool operator==(const Id<T>& a, const Id<T>& b) {
assert(a.group == b.group && "Cannot compare Ids from different groups");
return a.id == b.id;
}
template <typename T>
bool operator!=(const Id<T>& a, const Id<T>& b) {
return !(a == b);
}
using IndexTypeId = Id<IndexedTypeDef>;
using IndexFuncId = Id<IndexedFuncDef>;

View File

@ -22,6 +22,8 @@ const char* IpcIdToString(IpcId id) {
return "textDocument/completion";
case IpcId::TextDocumentDefinition:
return "textDocument/definition";
case IpcId::TextDocumentDocumentHighlight:
return "textDocument/documentHighlight";
case IpcId::TextDocumentHover:
return "textDocument/hover";
case IpcId::TextDocumentReferences:

View File

@ -16,6 +16,7 @@ enum class IpcId : int {
TextDocumentDidSave,
TextDocumentCompletion,
TextDocumentDefinition,
TextDocumentDocumentHighlight,
TextDocumentHover,
TextDocumentReferences,
TextDocumentDocumentSymbol,

View File

@ -166,6 +166,11 @@ std::string lsDocumentUri::GetPath() const {
}
std::replace(result.begin(), result.end(), '\\', '/');
#if defined(_WIN32)
//std::transform(result.begin(), result.end(), result.begin(), ::tolower);
#endif
return result;
}

View File

@ -488,6 +488,29 @@ struct lsTextDocumentEdit {
};
MAKE_REFLECT_STRUCT(lsTextDocumentEdit, textDocument, edits);
// A document highlight kind.
enum class lsDocumentHighlightKind {
// A textual occurrence.
Text = 1,
// Read-access of a symbol, like reading a variable.
Read = 2,
// Write-access of a symbol, like writing to a variable.
Write = 3
};
MAKE_REFLECT_TYPE_PROXY(lsDocumentHighlightKind, int);
// A document highlight is a range inside a text document which deserves
// special attention. Usually a document highlight is visualized by changing
// the background color of its range.
struct lsDocumentHighlight {
// The range this highlight applies to.
lsRange range;
// The highlight kind, default is DocumentHighlightKind.Text.
lsDocumentHighlightKind kind = lsDocumentHighlightKind::Text;
};
MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind);
// TODO: WorkspaceEdit
// TODO: DocumentFilter
// TODO: DocumentSelector
@ -1131,6 +1154,20 @@ struct Out_TextDocumentDefinition : public lsOutMessage<Out_TextDocumentDefiniti
};
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
// Document highlight
struct Ipc_TextDocumentDocumentHighlight : public IpcMessage<Ipc_TextDocumentDocumentHighlight> {
const static IpcId kIpcId = IpcId::TextDocumentDocumentHighlight;
lsRequestId id;
lsTextDocumentPositionParams params;
};
MAKE_REFLECT_STRUCT(Ipc_TextDocumentDocumentHighlight, id, params);
struct Out_TextDocumentDocumentHighlight : public lsOutMessage<Out_TextDocumentDocumentHighlight> {
lsRequestId id;
NonElidedVector<lsDocumentHighlight> result;
};
MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentHighlight, jsonrpc, id, result);
// Hover
struct Ipc_TextDocumentHover : public IpcMessage<Ipc_TextDocumentHover> {
const static IpcId kIpcId = IpcId::TextDocumentHover;

View File

@ -141,6 +141,7 @@ std::string NormalizePath(const std::string& path) {
std::string result = buffer;
std::replace(result.begin(), result.end(), '\\', '/');
//std::transform(result.begin(), result.end(), result.begin(), ::tolower);
return result;
}