summaryrefslogtreecommitdiff
path: root/lsp.c
blob: c35b6919080aad00f96a10ec0d48366616a6c976 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
typedef struct {
	Process process;
} LSP;

typedef struct {
	u32 pos;
	u32 len;
} JSONString;

typedef struct JSONValue JSONValue;

typedef struct {
	u32 len;
	u32 properties;
	u32 values;
} JSONObject;

typedef struct {
	u32 len;
	u32 values;
} JSONArray;

enum {
	JSON_NULL,
	JSON_FALSE,
	JSON_TRUE,
	JSON_NUMBER,
	JSON_STRING,
	JSON_OBJECT,
	JSON_ARRAY
};

struct JSONValue {
	u8 type;
	union {
		double number;
		JSONString string;
		JSONArray array;
		JSONObject object;
	} val;
};


typedef struct {
	const char *text;
	// root = values[0]
	JSONValue *values;
} JSON;

static bool json_parse_value(JSON *json, u32 *p_index, JSONValue *val) {
	const char *text = json->text;
	u32 index = *p_index;
	while (isspace(text[index])) ++index;
	switch (text[index]) {
	case '{':
		val->type = JSON_OBJECT;
		json_parse_object(json, &index, &val->val.object);
		break;
	case '[':
		val->type = JSON_ARRAY;
		json_parse_array(json, &index, &val->val.array);
		break;
	case '"':
		val->type = JSON_STRING;
		json_parse_string(json, &index, &val->val.string);
		break;
	case ANY_DIGIT:
		json_parse_number(json, &index, &val->val.number);
		break;
	case 'f':
		if (!str_is_prefix(&text[index], "false", 5) != 0) {
			
		}
	}
}

// NOTE: text must live as long as json!!!
static bool json_parse(JSON *json, const char *text) {
	memset(json, 0, sizeof *json);
	json->text = text;
	// @TODO: is this a good capacity?
	arr_reserve(json->values, strlen(text) / 8);
	arr_addp(json->values); // add root
	JSONValue val = {0};
	u32 index = 0;
	if (!json_parse_value(json, &index, &val))
		return false;
	
	while (isspace(text[index])) ++index;
	if (text[index]) {
		// more text after end of object
		// @TODO error message
		return false;
	}
	json->values[0] = val;
}

static void send_message(LSP *lsp, const char *content) {
	char header[128];
	size_t content_size = strlen(content);
	strbuf_printf(header, "Content-Length: %zu\r\n\r\n", content_size); 
	process_write(&lsp->process, header, strlen(header));
	process_write(&lsp->process, content, content_size);
}

void lsp_create(LSP *lsp, const char *analyzer_command) {
	ProcessSettings settings = {
		.stdin_blocking = true,
		.stdout_blocking = true
	};
	process_run_ex(&lsp->process, analyzer_command, &settings);
	char init_request[1024];
	strbuf_printf(init_request,
		"{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{"
			"\"processId\":%d,"
			"\"capabilities\":{}"
		"}}",
		process_get_id());
	send_message(lsp, init_request);
	char init_response[4096] = {0};
	process_read(&lsp->process, init_response, sizeof init_response);
	printf("%s\n",init_response);
}