Browse Source

basic code lens, still buggy

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

275
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> {
static constexpr IpcId kIpcId = IpcId::WorkspaceSymbolsResponse;
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) {
std::vector<std::unique_ptr<IpcMessage>> messages = language_client->TakeMessages();
@ -447,73 +520,121 @@ void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableD
IpcMessage_DocumentSymbolsResponse response;
response.request_id = msg->request_id;
std::cerr << "Wanted file " << msg->document << std::endl;
for (auto& file : db->files) {
std::cerr << " - Have file " << file.file_id << std::endl;
// 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];
lsSymbolInformation info;
info.location.range.start.line = ref.loc.line - 1; // TODO: cleanup indexer to negate by 1.
info.location.range.start.character = ref.loc.column - 1; // TODO: cleanup indexer to negate by 1.
// TODO: store range information.
info.location.range.end.line = info.location.range.start.line;
info.location.range.end.character = info.location.range.start.character;
// TODO: cleanup namespace/naming so there is only one SymbolKind.
switch (symbol.kind) {
case ::SymbolKind::Type:
{
QueryableTypeDef& def = db->types[symbol.idx];
info.name = def.def.qualified_name;
info.kind = lsSymbolKind::Class;
break;
}
case SymbolKind::Func:
{
QueryableFuncDef& def = db->funcs[symbol.idx];
info.name = def.def.qualified_name;
if (def.def.declaring_type.has_value()) {
info.kind = lsSymbolKind::Method;
Usr declaring = def.def.declaring_type.value();
info.containerName = db->types[db->usr_to_symbol[declaring].idx].def.qualified_name;
}
else {
info.kind = lsSymbolKind::Function;
}
break;
QueryableFile* file = FindFile(db, msg->document);
if (file) {
for (UsrRef ref : file->outline) {
SymbolIdx symbol = db->usr_to_symbol[ref.usr];
lsSymbolInformation info;
info.location.range.start.line = ref.loc.line - 1; // TODO: cleanup indexer to negate by 1.
info.location.range.start.character = ref.loc.column - 1; // TODO: cleanup indexer to negate by 1.
// TODO: store range information.
info.location.range.end.line = info.location.range.start.line;
info.location.range.end.character = info.location.range.start.character;
// TODO: cleanup namespace/naming so there is only one SymbolKind.
switch (symbol.kind) {
case ::SymbolKind::Type: {
QueryableTypeDef& def = db->types[symbol.idx];
info.name = def.def.qualified_name;
info.kind = lsSymbolKind::Class;
break;
}
case SymbolKind::Func: {
QueryableFuncDef& def = db->funcs[symbol.idx];
info.name = def.def.qualified_name;
if (def.def.declaring_type.has_value()) {
info.kind = lsSymbolKind::Method;
Usr declaring = def.def.declaring_type.value();
info.containerName = db->types[db->usr_to_symbol[declaring].idx].def.qualified_name;
}
case ::SymbolKind::Var:
{
QueryableVarDef& def = db->vars[symbol.idx];
info.name = def.def.qualified_name;
info.kind = lsSymbolKind::Variable;
break;
else {
info.kind = lsSymbolKind::Function;
}
};
break;
}
case ::SymbolKind::Var: {
QueryableVarDef& def = db->vars[symbol.idx];
info.name = def.def.qualified_name;
info.kind = lsSymbolKind::Variable;
break;
}
};
response.symbols.push_back(info);
}
}
language_client->SendToClient(0, &response);
break;
}
// TODO
//info.containerName = "fooey";
case IpcId::DocumentCodeLensRequest: {
auto msg = static_cast<IpcMessage_DocumentCodeLensRequest*>(message.get());
response.symbols.push_back(info);
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;
}
case SymbolKind::Func: {
QueryableFuncDef& def = db->funcs[symbol.idx];
for (QueryableLocation& usage : def.uses)
code_lens.command->arguments.locations.push_back(GetLsLocation(usage));
break;
}
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);
break;
}
@ -588,20 +709,14 @@ void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableD
};
// TODO: store range information.
info.location.range.end.line = info.location.range.start.line;
info.location.range.end.character = info.location.range.start.character;
response.symbols.push_back(info);
}
}
language_client->SendToClient(0, &response);
break;
}
@ -743,6 +858,9 @@ void LanguageServerStdinLoop(IpcClient* server) {
auto response = Out_InitializeResponse();
response.id = message->id.value();
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.Send();
break;
@ -762,6 +880,18 @@ void LanguageServerStdinLoop(IpcClient* server) {
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:
{
auto request = static_cast<In_WorkspaceSymbolRequest*>(message.get());
@ -792,7 +922,18 @@ void LanguageServerMainLoop(IpcClient* ipc) {
response.id = msg->request_id;
response.result = msg->symbols;
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;
}
@ -858,7 +999,7 @@ void LanguageServerMain(std::string process_name) {
// Pass empty process name so we only try to start the querydb once.
LanguageServerMain("");
return;
}
}
#endif
// for debugging attach
@ -946,6 +1087,11 @@ void PreMain() {
IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsRequest>(IpcMessage_DocumentSymbolsRequest::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_WorkspaceSymbolsResponse>(IpcMessage_WorkspaceSymbolsResponse::kIpcId);
@ -953,6 +1099,7 @@ void PreMain() {
MessageRegistry::instance()->Register<In_InitializeRequest>();
MessageRegistry::instance()->Register<In_InitializedNotification>();
MessageRegistry::instance()->Register<In_DocumentSymbolRequest>();
MessageRegistry::instance()->Register<In_DocumentCodeLensRequest>();
MessageRegistry::instance()->Register<In_WorkspaceSymbolRequest>();
}

4
ipc.h

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

157
language_server_api.h

@ -24,6 +24,8 @@ enum class lsMethodId : int {
Initialize,
Initialized,
TextDocumentDocumentSymbol,
TextDocumentCodeLens,
CodeLensResolve,
WorkspaceSymbol,
};
@ -240,6 +242,10 @@ const char* MethodIdToString(lsMethodId id) {
return "initialized";
case lsMethodId::TextDocumentDocumentSymbol:
return "textDocument/documentSymbol";
case lsMethodId::TextDocumentCodeLens:
return "textDocument/codeLens";
case lsMethodId::CodeLensResolve:
return "codeLens/resolve";
case lsMethodId::WorkspaceSymbol:
return "workspace/symbol";
default:
@ -392,6 +398,14 @@ struct In_CancelRequest : public InNotificationMessage {
struct lsDocumentUri {
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) {
// file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests
raw_uri = path;
@ -434,6 +448,9 @@ struct lsPosition {
// Note: these are 0-based.
int line = 0;
int character = 0;
lsPosition() {}
lsPosition(int line, int character) : line(line), character(character) {}
};
template<typename TVisitor>
@ -448,6 +465,9 @@ void Reflect(TVisitor& visitor, lsPosition& value) {
struct lsRange {
lsPosition start;
lsPosition end;
lsRange() {}
lsRange(lsPosition position) : start(position), end(position) {}
};
template<typename TVisitor>
@ -462,6 +482,9 @@ void Reflect(TVisitor& visitor, lsRange& value) {
struct lsLocation {
lsDocumentUri uri;
lsRange range;
lsLocation() {}
lsLocation(lsDocumentUri uri, lsRange range) : uri(uri), range(range) {}
};
template<typename TVisitor>
@ -520,18 +543,18 @@ void Reflect(TVisitor& visitor, lsSymbolInformation& value) {
REFLECT_MEMBER_END();
}
template<typename T>
struct lsCommand {
// Title of the command (ie, 'save')
std::string title;
// Actual command identifier.
std::string command;
// Arguments to run the command with. Could be JSON objects.
std::vector<std::string> arguments;
// Arguments to run the command with.
T arguments;
};
template<typename TVisitor>
void Reflect(TVisitor& visitor, lsCommand& value) {
template<typename TVisitor, typename T>
void Reflect(TVisitor& visitor, lsCommand<T>& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(title);
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: WorkspaceEdit
@ -800,8 +843,13 @@ struct lsTextDocumentClientCapabilities {
// Capabilities specific to the `textDocument/codeAction`
optional<lsGenericDynamicReg> codeAction;
struct CodeLensRegistrationOptions : public lsGenericDynamicReg {
// Code lens has a resolve provider as well.
bool resolveProvider;
};
// Capabilities specific to the `textDocument/codeLens`
optional<lsGenericDynamicReg> codeLens;
optional<CodeLensRegistrationOptions> codeLens;
// Capabilities specific to the `textDocument/documentLink`
optional<lsGenericDynamicReg> documentLink;
@ -842,6 +890,14 @@ void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities::lsGenericDynam
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>
void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities& value) {
REFLECT_MEMBER_START();
@ -1281,7 +1337,6 @@ struct In_DocumentSymbolRequest : public InRequestMessage {
}
};
struct Out_DocumentSymbolResponse : public OutResponseMessage {
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 {
std::vector<lsSymbolInformation> result;

Loading…
Cancel
Save