Browse Source

basic code lens, still buggy

pull/2/head
Jacob Dufault 8 years ago
parent
commit
ec8bf8a113
  1. 205
      command_line.cc
  2. 4
      ipc.h
  3. 157
      language_server_api.h

205
command_line.cc

@ -276,6 +276,62 @@ void Reflect(TVisitor& visitor, IpcMessage_WorkspaceSymbolsRequest& value) {
} }
struct IpcMessage_DocumentCodeLensRequest : public BaseIpcMessage<IpcMessage_DocumentCodeLensRequest> {
static constexpr IpcId kIpcId = IpcId::DocumentCodeLensRequest;
RequestId request_id;
std::string document;
};
template<typename TVisitor>
void Reflect(TVisitor& visitor, IpcMessage_DocumentCodeLensRequest& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(request_id);
REFLECT_MEMBER(document);
REFLECT_MEMBER_END();
}
struct IpcMessage_DocumentCodeLensResponse : public BaseIpcMessage<IpcMessage_DocumentCodeLensResponse> {
static constexpr IpcId kIpcId = IpcId::DocumentCodeLensResponse;
RequestId request_id;
std::vector<TCodeLens> code_lens;
};
template<typename TVisitor>
void Reflect(TVisitor& visitor, IpcMessage_DocumentCodeLensResponse& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(request_id);
REFLECT_MEMBER(code_lens);
REFLECT_MEMBER_END();
}
struct IpcMessage_CodeLensResolveRequest : public BaseIpcMessage<IpcMessage_CodeLensResolveRequest> {
static constexpr IpcId kIpcId = IpcId::CodeLensResolveRequest;
RequestId request_id;
TCodeLens code_lens;
};
template<typename TVisitor>
void Reflect(TVisitor& visitor, IpcMessage_CodeLensResolveRequest& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(request_id);
REFLECT_MEMBER(code_lens);
REFLECT_MEMBER_END();
}
struct IpcMessage_CodeLensResolveResponse : public BaseIpcMessage<IpcMessage_CodeLensResolveResponse> {
static constexpr IpcId kIpcId = IpcId::CodeLensResolveResponse;
RequestId request_id;
TCodeLens code_lens;
};
template<typename TVisitor>
void Reflect(TVisitor& visitor, IpcMessage_CodeLensResolveResponse& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(request_id);
REFLECT_MEMBER(code_lens);
REFLECT_MEMBER_END();
}
struct IpcMessage_WorkspaceSymbolsResponse : public BaseIpcMessage<IpcMessage_WorkspaceSymbolsResponse> { struct IpcMessage_WorkspaceSymbolsResponse : public BaseIpcMessage<IpcMessage_WorkspaceSymbolsResponse> {
static constexpr IpcId kIpcId = IpcId::WorkspaceSymbolsResponse; static constexpr IpcId kIpcId = IpcId::WorkspaceSymbolsResponse;
RequestId request_id; RequestId request_id;
@ -394,12 +450,29 @@ void IndexMain(int id) {
QueryableFile* FindFile(QueryableDatabase* db, const std::string& filename) {
//std::cerr << "Wanted file " << msg->document << std::endl;
// TODO: hashmap lookup.
for (auto& file : db->files) {
//std::cerr << " - Have file " << file.file_id << std::endl;
if (file.file_id == filename) {
std::cerr << "Found file " << filename << std::endl;
return &file;
}
}
std::cerr << "Unable to find file " << filename << std::endl;
return nullptr;
}
lsLocation GetLsLocation(QueryableLocation& location) {
return lsLocation(
lsDocumentUri::FromPath(location.path),
lsRange(lsPosition(location.line - 1, location.column - 1)));
}
void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableDatabase* db) { void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableDatabase* db) {
std::vector<std::unique_ptr<IpcMessage>> messages = language_client->TakeMessages(); std::vector<std::unique_ptr<IpcMessage>> messages = language_client->TakeMessages();
@ -447,17 +520,9 @@ void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableD
IpcMessage_DocumentSymbolsResponse response; IpcMessage_DocumentSymbolsResponse response;
response.request_id = msg->request_id; response.request_id = msg->request_id;
std::cerr << "Wanted file " << msg->document << std::endl; QueryableFile* file = FindFile(db, msg->document);
for (auto& file : db->files) { if (file) {
std::cerr << " - Have file " << file.file_id << std::endl; for (UsrRef ref : file->outline) {
// TODO: make sure we normalize ids!
// TODO: hashmap lookup.
if (file.file_id == msg->document) {
std::cerr << "Found file" << std::endl;
for (UsrRef ref : file.outline) {
SymbolIdx symbol = db->usr_to_symbol[ref.usr]; SymbolIdx symbol = db->usr_to_symbol[ref.usr];
lsSymbolInformation info; lsSymbolInformation info;
@ -469,15 +534,13 @@ void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableD
// TODO: cleanup namespace/naming so there is only one SymbolKind. // TODO: cleanup namespace/naming so there is only one SymbolKind.
switch (symbol.kind) { switch (symbol.kind) {
case ::SymbolKind::Type: case ::SymbolKind::Type: {
{
QueryableTypeDef& def = db->types[symbol.idx]; QueryableTypeDef& def = db->types[symbol.idx];
info.name = def.def.qualified_name; info.name = def.def.qualified_name;
info.kind = lsSymbolKind::Class; info.kind = lsSymbolKind::Class;
break; break;
} }
case SymbolKind::Func: case SymbolKind::Func: {
{
QueryableFuncDef& def = db->funcs[symbol.idx]; QueryableFuncDef& def = db->funcs[symbol.idx];
info.name = def.def.qualified_name; info.name = def.def.qualified_name;
if (def.def.declaring_type.has_value()) { if (def.def.declaring_type.has_value()) {
@ -490,8 +553,7 @@ void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableD
} }
break; break;
} }
case ::SymbolKind::Var: case ::SymbolKind::Var: {
{
QueryableVarDef& def = db->vars[symbol.idx]; QueryableVarDef& def = db->vars[symbol.idx];
info.name = def.def.qualified_name; info.name = def.def.qualified_name;
info.kind = lsSymbolKind::Variable; info.kind = lsSymbolKind::Variable;
@ -499,21 +561,80 @@ void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableD
} }
}; };
// TODO
//info.containerName = "fooey";
response.symbols.push_back(info); response.symbols.push_back(info);
}
}
language_client->SendToClient(0, &response);
break;
}
case IpcId::DocumentCodeLensRequest: {
auto msg = static_cast<IpcMessage_DocumentCodeLensRequest*>(message.get());
IpcMessage_DocumentCodeLensResponse response;
response.request_id = msg->request_id;
lsDocumentUri file_as_uri;
file_as_uri.SetPath(msg->document);
QueryableFile* file = FindFile(db, msg->document);
if (file) {
for (UsrRef ref : file->outline) {
SymbolIdx symbol = db->usr_to_symbol[ref.usr];
TCodeLens code_lens;
code_lens.range.start.line = ref.loc.line - 1; // TODO: cleanup indexer to negate by 1.
code_lens.range.start.character = ref.loc.column - 1; // TODO: cleanup indexer to negate by 1.
// TODO: store range information.
code_lens.range.end.line = code_lens.range.start.line;
code_lens.range.end.character = code_lens.range.start.character;
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
code_lens.command->command = "superindex.showReferences";
code_lens.command->arguments.uri = file_as_uri;
code_lens.command->arguments.position = code_lens.range.start;
switch (symbol.kind) {
case SymbolKind::Type: {
QueryableTypeDef& def = db->types[symbol.idx];
for (QueryableLocation& usage : def.uses) {
if (!usage.interesting)
continue;
code_lens.command->arguments.locations.push_back(GetLsLocation(usage));
} }
break; break;
} }
case SymbolKind::Func: {
QueryableFuncDef& def = db->funcs[symbol.idx];
for (QueryableLocation& usage : def.uses)
code_lens.command->arguments.locations.push_back(GetLsLocation(usage));
break;
} }
case SymbolKind::Var: {
QueryableVarDef& def = db->vars[symbol.idx];
for (QueryableLocation& usage : def.uses)
code_lens.command->arguments.locations.push_back(GetLsLocation(usage));
break;
}
};
// TODO: we are getting too many references
int num_usages = code_lens.command->arguments.locations.size();
code_lens.command->title = std::to_string(num_usages) + " reference";
if (num_usages != 1)
code_lens.command->title += "s";
response.code_lens.push_back(code_lens);
}
language_client->SendToClient(0, &response); }
language_client->SendToClient(0, &response);
break; break;
} }
@ -588,20 +709,14 @@ void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableD
}; };
// TODO: store range information. // TODO: store range information.
info.location.range.end.line = info.location.range.start.line; info.location.range.end.line = info.location.range.start.line;
info.location.range.end.character = info.location.range.start.character; info.location.range.end.character = info.location.range.start.character;
response.symbols.push_back(info); response.symbols.push_back(info);
} }
} }
language_client->SendToClient(0, &response); language_client->SendToClient(0, &response);
break; break;
} }
@ -743,6 +858,9 @@ void LanguageServerStdinLoop(IpcClient* server) {
auto response = Out_InitializeResponse(); auto response = Out_InitializeResponse();
response.id = message->id.value(); response.id = message->id.value();
response.result.capabilities.documentSymbolProvider = true; response.result.capabilities.documentSymbolProvider = true;
//response.result.capabilities.referencesProvider = true;
response.result.capabilities.codeLensProvider = lsCodeLensOptions();
response.result.capabilities.codeLensProvider->resolveProvider = false;
response.result.capabilities.workspaceSymbolProvider = true; response.result.capabilities.workspaceSymbolProvider = true;
response.Send(); response.Send();
break; break;
@ -762,6 +880,18 @@ void LanguageServerStdinLoop(IpcClient* server) {
break; break;
} }
case lsMethodId::TextDocumentCodeLens:
{
auto request = static_cast<In_DocumentCodeLensRequest*>(message.get());
IpcMessage_DocumentCodeLensRequest ipc_request;
ipc_request.request_id = request->id.value();
ipc_request.document = request->params.textDocument.uri.GetPath();
std::cerr << "Request codeLens on textDocument=" << ipc_request.document << std::endl;
server->SendToServer(&ipc_request);
break;
}
case lsMethodId::WorkspaceSymbol: case lsMethodId::WorkspaceSymbol:
{ {
auto request = static_cast<In_WorkspaceSymbolRequest*>(message.get()); auto request = static_cast<In_WorkspaceSymbolRequest*>(message.get());
@ -792,7 +922,18 @@ void LanguageServerMainLoop(IpcClient* ipc) {
response.id = msg->request_id; response.id = msg->request_id;
response.result = msg->symbols; response.result = msg->symbols;
response.Send(); response.Send();
std::cerr << "Send symbol response to client (" << response.result.size() << " symbols)" << std::endl; std::cerr << "Sent symbol response to client (" << response.result.size() << " symbols)" << std::endl;
break;
}
case IpcId::DocumentCodeLensResponse: {
auto msg = static_cast<IpcMessage_DocumentCodeLensResponse*>(message.get());
auto response = Out_DocumentCodeLensResponse();
response.id = msg->request_id;
response.result = msg->code_lens;
response.Send();
std::cerr << "Sent code lens response to client (" << response.result.size() << " symbols)" << std::endl;
break; break;
} }
@ -946,6 +1087,11 @@ void PreMain() {
IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsRequest>(IpcMessage_DocumentSymbolsRequest::kIpcId); IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsRequest>(IpcMessage_DocumentSymbolsRequest::kIpcId);
IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsResponse>(IpcMessage_DocumentSymbolsResponse::kIpcId); IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsResponse>(IpcMessage_DocumentSymbolsResponse::kIpcId);
IpcRegistry::instance()->Register<IpcMessage_DocumentCodeLensRequest>(IpcMessage_DocumentCodeLensRequest::kIpcId);
IpcRegistry::instance()->Register<IpcMessage_DocumentCodeLensResponse>(IpcMessage_DocumentCodeLensResponse::kIpcId);
IpcRegistry::instance()->Register<IpcMessage_CodeLensResolveRequest>(IpcMessage_CodeLensResolveRequest::kIpcId);
IpcRegistry::instance()->Register<IpcMessage_CodeLensResolveResponse>(IpcMessage_CodeLensResolveResponse::kIpcId);
IpcRegistry::instance()->Register<IpcMessage_WorkspaceSymbolsRequest>(IpcMessage_WorkspaceSymbolsRequest::kIpcId); IpcRegistry::instance()->Register<IpcMessage_WorkspaceSymbolsRequest>(IpcMessage_WorkspaceSymbolsRequest::kIpcId);
IpcRegistry::instance()->Register<IpcMessage_WorkspaceSymbolsResponse>(IpcMessage_WorkspaceSymbolsResponse::kIpcId); IpcRegistry::instance()->Register<IpcMessage_WorkspaceSymbolsResponse>(IpcMessage_WorkspaceSymbolsResponse::kIpcId);
@ -953,6 +1099,7 @@ void PreMain() {
MessageRegistry::instance()->Register<In_InitializeRequest>(); MessageRegistry::instance()->Register<In_InitializeRequest>();
MessageRegistry::instance()->Register<In_InitializedNotification>(); MessageRegistry::instance()->Register<In_InitializedNotification>();
MessageRegistry::instance()->Register<In_DocumentSymbolRequest>(); MessageRegistry::instance()->Register<In_DocumentSymbolRequest>();
MessageRegistry::instance()->Register<In_DocumentCodeLensRequest>();
MessageRegistry::instance()->Register<In_WorkspaceSymbolRequest>(); MessageRegistry::instance()->Register<In_WorkspaceSymbolRequest>();
} }

4
ipc.h

@ -33,6 +33,10 @@ enum class IpcId : int {
// TODO: remove // TODO: remove
DocumentSymbolsRequest, DocumentSymbolsRequest,
DocumentSymbolsResponse, DocumentSymbolsResponse,
DocumentCodeLensRequest,
DocumentCodeLensResponse,
CodeLensResolveRequest,
CodeLensResolveResponse,
WorkspaceSymbolsRequest, WorkspaceSymbolsRequest,
WorkspaceSymbolsResponse WorkspaceSymbolsResponse
}; };

157
language_server_api.h

@ -24,6 +24,8 @@ enum class lsMethodId : int {
Initialize, Initialize,
Initialized, Initialized,
TextDocumentDocumentSymbol, TextDocumentDocumentSymbol,
TextDocumentCodeLens,
CodeLensResolve,
WorkspaceSymbol, WorkspaceSymbol,
}; };
@ -240,6 +242,10 @@ const char* MethodIdToString(lsMethodId id) {
return "initialized"; return "initialized";
case lsMethodId::TextDocumentDocumentSymbol: case lsMethodId::TextDocumentDocumentSymbol:
return "textDocument/documentSymbol"; return "textDocument/documentSymbol";
case lsMethodId::TextDocumentCodeLens:
return "textDocument/codeLens";
case lsMethodId::CodeLensResolve:
return "codeLens/resolve";
case lsMethodId::WorkspaceSymbol: case lsMethodId::WorkspaceSymbol:
return "workspace/symbol"; return "workspace/symbol";
default: default:
@ -392,6 +398,14 @@ struct In_CancelRequest : public InNotificationMessage {
struct lsDocumentUri { struct lsDocumentUri {
std::string raw_uri; std::string raw_uri;
lsDocumentUri() {}
static lsDocumentUri FromPath(const std::string& path) {
lsDocumentUri result;
result.SetPath(path);
return result;
}
void SetPath(const std::string& path) { void SetPath(const std::string& path) {
// file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests // file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests
raw_uri = path; raw_uri = path;
@ -434,6 +448,9 @@ struct lsPosition {
// Note: these are 0-based. // Note: these are 0-based.
int line = 0; int line = 0;
int character = 0; int character = 0;
lsPosition() {}
lsPosition(int line, int character) : line(line), character(character) {}
}; };
template<typename TVisitor> template<typename TVisitor>
@ -448,6 +465,9 @@ void Reflect(TVisitor& visitor, lsPosition& value) {
struct lsRange { struct lsRange {
lsPosition start; lsPosition start;
lsPosition end; lsPosition end;
lsRange() {}
lsRange(lsPosition position) : start(position), end(position) {}
}; };
template<typename TVisitor> template<typename TVisitor>
@ -462,6 +482,9 @@ void Reflect(TVisitor& visitor, lsRange& value) {
struct lsLocation { struct lsLocation {
lsDocumentUri uri; lsDocumentUri uri;
lsRange range; lsRange range;
lsLocation() {}
lsLocation(lsDocumentUri uri, lsRange range) : uri(uri), range(range) {}
}; };
template<typename TVisitor> template<typename TVisitor>
@ -520,18 +543,18 @@ void Reflect(TVisitor& visitor, lsSymbolInformation& value) {
REFLECT_MEMBER_END(); REFLECT_MEMBER_END();
} }
template<typename T>
struct lsCommand { struct lsCommand {
// Title of the command (ie, 'save') // Title of the command (ie, 'save')
std::string title; std::string title;
// Actual command identifier. // Actual command identifier.
std::string command; std::string command;
// Arguments to run the command with. Could be JSON objects. // Arguments to run the command with.
std::vector<std::string> arguments; T arguments;
}; };
template<typename TVisitor> template<typename TVisitor, typename T>
void Reflect(TVisitor& visitor, lsCommand& value) { void Reflect(TVisitor& visitor, lsCommand<T>& value) {
REFLECT_MEMBER_START(); REFLECT_MEMBER_START();
REFLECT_MEMBER(title); REFLECT_MEMBER(title);
REFLECT_MEMBER(command); REFLECT_MEMBER(command);
@ -540,6 +563,26 @@ void Reflect(TVisitor& visitor, lsCommand& value) {
} }
template<typename TData, typename TCommandArguments>
struct lsCodeLens {
// The range in which this code lens is valid. Should only span a single line.
lsRange range;
// The command this code lens represents.
optional<lsCommand<TCommandArguments>> command;
// A data entry field that is preserved on a code lens item between
// a code lens and a code lens resolve request.
TData data;
};
template<typename TVisitor, typename TData, typename TCommandArguments>
void Reflect(TVisitor& visitor, lsCodeLens<TData, TCommandArguments>& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(range);
REFLECT_MEMBER(command);
REFLECT_MEMBER(data);
REFLECT_MEMBER_END();
}
// TODO: TextDocumentEdit // TODO: TextDocumentEdit
// TODO: WorkspaceEdit // TODO: WorkspaceEdit
@ -800,8 +843,13 @@ struct lsTextDocumentClientCapabilities {
// Capabilities specific to the `textDocument/codeAction` // Capabilities specific to the `textDocument/codeAction`
optional<lsGenericDynamicReg> codeAction; optional<lsGenericDynamicReg> codeAction;
struct CodeLensRegistrationOptions : public lsGenericDynamicReg {
// Code lens has a resolve provider as well.
bool resolveProvider;
};
// Capabilities specific to the `textDocument/codeLens` // Capabilities specific to the `textDocument/codeLens`
optional<lsGenericDynamicReg> codeLens; optional<CodeLensRegistrationOptions> codeLens;
// Capabilities specific to the `textDocument/documentLink` // Capabilities specific to the `textDocument/documentLink`
optional<lsGenericDynamicReg> documentLink; optional<lsGenericDynamicReg> documentLink;
@ -842,6 +890,14 @@ void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities::lsGenericDynam
REFLECT_MEMBER_END(); REFLECT_MEMBER_END();
} }
template<typename TVisitor>
void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities::CodeLensRegistrationOptions& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(dynamicRegistration);
REFLECT_MEMBER(resolveProvider);
REFLECT_MEMBER_END();
}
template<typename TVisitor> template<typename TVisitor>
void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities& value) { void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities& value) {
REFLECT_MEMBER_START(); REFLECT_MEMBER_START();
@ -1281,7 +1337,6 @@ struct In_DocumentSymbolRequest : public InRequestMessage {
} }
}; };
struct Out_DocumentSymbolResponse : public OutResponseMessage { struct Out_DocumentSymbolResponse : public OutResponseMessage {
std::vector<lsSymbolInformation> result; std::vector<lsSymbolInformation> result;
@ -1295,6 +1350,93 @@ struct Out_DocumentSymbolResponse : public OutResponseMessage {
struct lsDocumentCodeLensParams {
lsTextDocumentIdentifier textDocument;
};
template<typename TVisitor>
void Reflect(TVisitor& visitor, lsDocumentCodeLensParams& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(textDocument);
REFLECT_MEMBER_END();
}
struct lsCodeLensUserData {};
template<typename TVisitor>
void Reflect(TVisitor& visitor, lsCodeLensUserData& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER_END();
}
struct lsCodeLensCommandArguments {
lsDocumentUri uri;
lsPosition position;
std::vector<lsLocation> locations;
};
void Reflect(Writer& visitor, lsCodeLensCommandArguments& value) {
visitor.StartArray();
Reflect(visitor, value.uri);
Reflect(visitor, value.position);
Reflect(visitor, value.locations);
visitor.EndArray();
}
void Reflect(Reader& visitor, lsCodeLensCommandArguments& value) {
auto it = visitor.Begin();
Reflect(*it, value.uri);
++it;
Reflect(*it, value.position);
++it;
Reflect(*it, value.locations);
}
using TCodeLens = lsCodeLens<lsCodeLensUserData, lsCodeLensCommandArguments>;
struct In_DocumentCodeLensRequest : public InRequestMessage {
const static lsMethodId kMethod = lsMethodId::TextDocumentCodeLens;
lsDocumentCodeLensParams params;
In_DocumentCodeLensRequest(optional<RequestId> id, Reader& reader)
: InRequestMessage(kMethod, id, reader) {
Reflect(reader, params);
}
};
struct Out_DocumentCodeLensResponse : public OutResponseMessage {
std::vector<lsCodeLens<lsCodeLensUserData, lsCodeLensCommandArguments>> result;
// OutResponseMessage:
void WriteResult(Writer& writer) override {
::Reflect(writer, result);
}
};
struct In_DocumentCodeLensResolveRequest : public InRequestMessage {
const static lsMethodId kMethod = lsMethodId::CodeLensResolve;
TCodeLens params;
In_DocumentCodeLensResolveRequest(optional<RequestId> id, Reader& reader)
: InRequestMessage(kMethod, id, reader) {
Reflect(reader, params);
}
};
struct Out_DocumentCodeLensResolveResponse : public OutResponseMessage {
TCodeLens result;
// OutResponseMessage:
void WriteResult(Writer& writer) override {
::Reflect(writer, result);
}
};
@ -1321,7 +1463,6 @@ struct In_WorkspaceSymbolRequest : public InRequestMessage {
} }
}; };
struct Out_WorkspaceSymbolResponse : public OutResponseMessage { struct Out_WorkspaceSymbolResponse : public OutResponseMessage {
std::vector<lsSymbolInformation> result; std::vector<lsSymbolInformation> result;

Loading…
Cancel
Save