Skip to content

Commit

Permalink
Add LSP hover information
Browse files Browse the repository at this point in the history
  • Loading branch information
BojanStipic committed Jun 5, 2019
1 parent 6fe2abc commit 8c26c03
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 4 deletions.
1 change: 1 addition & 0 deletions defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ enum severity { ERROR = 1, WARNING, INFORMATION, HINT };

// Data types
enum types { NO_TYPE, INT, UINT };
static const char *types_str[] = { "void", "int", "unsigned int" };

// Kinds of symbols (maximum 32 different kinds)
enum kinds { NO_KIND = 0x1, REG = 0x2, LIT = 0x4,
Expand Down
69 changes: 69 additions & 0 deletions lsp.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <cjson/cJSON.h>
#include "lsp.h"
#define MAX_HEADER_FIELD_LEN 100
void parse(cJSON *diagnostics, const char *text);
char* symbol_info(const char *symbol_name, const char *text);

void lsp_event_loop(void) {
for(;;) {
Expand Down Expand Up @@ -93,6 +95,9 @@ void json_rpc(const cJSON *request) {
else if(strcmp(method, "textDocument/didChange") == 0) {
lsp_text_sync("didChange", params_json);
}
else if(strcmp(method, "textDocument/hover") == 0) {
lsp_hover(id, params_json);
}
}

void lsp_send_response(int id, cJSON *result) {
Expand Down Expand Up @@ -133,6 +138,7 @@ void lsp_initialize(int id) {
cJSON *result = cJSON_CreateObject();
cJSON *capabilities = cJSON_CreateObject();
cJSON_AddNumberToObject(capabilities, "textDocumentSync", 1);
cJSON_AddBoolToObject(capabilities, "hoverProvider", 1);
// TODO add other capabilities

cJSON_AddItemToObject(result, "capabilities", capabilities);
Expand Down Expand Up @@ -185,3 +191,66 @@ void lsp_lint(const char *uri, const char *text) {
parse(diagnostics, text);
lsp_send_notification("textDocument/publishDiagnostics", params);
}

char* read_to_string(const char *uri) {
// uri + 7 -> skips file://
FILE *f = fopen(uri + 7, "r");
fseek(f, 0, SEEK_END);
unsigned long fsize = ftell(f);
rewind(f);

char *text = malloc(fsize + 1);
if(text == NULL)
exit(2);
fread(text, 1, fsize, f);
fclose(f);

text[fsize] = '\0';
return text;
}

const char* truncate_string(char *text, int line, int character) {
int position = 0;
for(int i = 0; i < line; i++) {
position += strcspn(text + position, "\n") + 1;
}
position += character;
int id_begin = position;

while(isalnum(*(text + position))) {
++position;
}
text[position] = '\0';

return text + id_begin;
}

void lsp_hover(int id, const cJSON *params_json) {
const cJSON *text_document_json = cJSON_GetObjectItem(params_json, "textDocument");
const cJSON *uri_json = cJSON_GetObjectItem(text_document_json, "uri");
const char *uri = NULL;
if(cJSON_IsString(uri_json) && (uri_json->valuestring != NULL)) {
uri = uri_json->valuestring;
}

const cJSON *position_json = cJSON_GetObjectItem(params_json, "position");
const cJSON *line_json = cJSON_GetObjectItem(position_json, "line");
int line;
if(cJSON_IsNumber(line_json)) {
line = line_json->valueint;
}
int character;
const cJSON *character_json = cJSON_GetObjectItem(position_json, "character");
if(cJSON_IsNumber(character_json)) {
character = character_json->valueint;
}

char *text = read_to_string(uri);
const char *symbol_name = truncate_string(text, line, character);
char *contents = symbol_info(symbol_name, text);
free(text);

cJSON *result = cJSON_CreateObject();
cJSON_AddStringToObject(result, "contents", contents);
lsp_send_response(id, result);
}
4 changes: 4 additions & 0 deletions lsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,9 @@ void lsp_text_sync(const char *method, const cJSON *params_json);
* Runs a linter and returns LSP publish diagnostics notification.
*/
void lsp_lint(const char *uri, const char *text);
/*
* Parses LSP hover request, and returns hover information.
*/
void lsp_hover(int id, const cJSON *params_json);

#endif
16 changes: 14 additions & 2 deletions minic.y
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%{
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "defs.h"
#include "symtab.h"
#include <cjson/cJSON.h>
Expand Down Expand Up @@ -267,10 +267,22 @@ void parse(cJSON *diagnostics, const char *text) {
YY_BUFFER_STATE buffer = yy_scan_string(text);
yyparse();
yy_delete_buffer(buffer);
clear_symtab();
_diagnostics = NULL;
}

char* symbol_info(const char *symbol_name, const char *text) {
parse(NULL, text);
int idx = lookup_symbol(symbol_name, VAR|PAR|FUN);
const char *type = types_str[get_type(idx)];
const char *name = get_name(idx);

char *info = malloc(strlen(type) + strlen(name) + 2);
strcpy(info, type);
strcat(info, " ");
strcat(info, name);
return info;
}

int main() {
lsp_event_loop();
return 0;
Expand Down
2 changes: 1 addition & 1 deletion symtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ int insert_literal(char *str, unsigned type) {
* Returns index of the found element.
* If the element is not found, returns -1.
*/
int lookup_symbol(char *name, unsigned kind) {
int lookup_symbol(const char *name, unsigned kind) {
int i;
for(i = first_empty - 1; i > FUN_REG; i--) {
if(strcmp(symbol_table[i].name, name) == 0
Expand Down
2 changes: 1 addition & 1 deletion symtab.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ int insert_literal(char *str, unsigned type);
* Returns index of the found element.
* If the element is not found, returns -1.
*/
int lookup_symbol(char *name, unsigned kind);
int lookup_symbol(const char *name, unsigned kind);

// Setters and getters for element fields.
void set_name(int index, char *name);
Expand Down

0 comments on commit 8c26c03

Please sign in to comment.