aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2020-11-18 22:14:33 +0100
committerDanielGavin <danielgavin5@hotmail.com>2020-11-18 22:14:33 +0100
commit3370a5e546ea9355068ba99b5e81f80527d2e582 (patch)
tree5a93eda4e2a5be4ec58d3ddf2595fa7dc1016cb3 /src/server
parentee4a7f64bcb9d6d7b60d5495fc072b2a62b5f790 (diff)
fixed all the memory leaks
Diffstat (limited to 'src/server')
-rw-r--r--src/server/analysis.odin77
-rw-r--r--src/server/documents.odin45
-rw-r--r--src/server/requests.odin40
-rw-r--r--src/server/unmarshal.odin4
4 files changed, 106 insertions, 60 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index f4b9ddd..3f52e69 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -752,7 +752,7 @@ make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type
for n in field.names {
identifier := n.derived.(ast.Ident);
append(&names, identifier.name);
- append(&types, ast.clone_expr(field.type));
+ append(&types, index.clone_type(field.type, context.temp_allocator));
}
}
@@ -973,8 +973,6 @@ get_definition_location :: proc(document: ^Document, position: common.Position)
get_completion_list :: proc(document: ^Document, position: common.Position) -> (CompletionList, bool) {
- symbols := make([dynamic] index.Symbol, context.temp_allocator);
-
list: CompletionList;
ast_context := make_ast_context(document.ast, document.imports, document.package_name);
@@ -992,6 +990,8 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> (
if position_context.selector != nil {
+ symbols := make([dynamic] index.Symbol, context.temp_allocator);
+
selector: index.Symbol;
selector, ok = resolve_type_expression(&ast_context, position_context.selector);
@@ -1057,19 +1057,72 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> (
}
}
+ for symbol, i in symbols {
+ item := CompletionItem {
+ label = symbol.name,
+ kind = cast(CompletionItemKind) symbol.type,
+ };
+
+ append(&items, item);
+ }
+
+ //if there is no field we had to recover from bad expr and create a node (remove when parser can accept temp_allocator)
+ if position_context.field == nil {
+ common.free_ast(position_context.selector);
+ }
+
+ list.items = items[:];
}
else {
- return list, true;
- }
- list.items = make([] CompletionItem, len(symbols), context.temp_allocator);
+ /*
+ Just show the local and global symbols of the document
+
+ TODO(Add fuzzy matching)
+ */
+
+ for k, v in ast_context.locals {
+
+ item := CompletionItem {
+ label = k,
+ };
+
+
+ append(&items, item);
+ }
+
+ for k, v in ast_context.globals {
+
+ item := CompletionItem {
+ label = k,
+ };
- for symbol, i in symbols {
- list.items[i].label = symbol.name;
- list.items[i].kind = cast(CompletionItemKind) symbol.type;
+ append(&items, item);
+ }
+
+ ident := index.new_type(ast.Ident, tokenizer.Pos {}, tokenizer.Pos {}, context.temp_allocator);
+
+ for item, i in items {
+
+ ident.name = item.label;
+
+ if symbol, ok := resolve_type_identifier(&ast_context, ident^, true); ok {
+ items[i].kind = .Variable;
+ }
+
+ else if symbol, ok := resolve_type_identifier(&ast_context, ident^, false); ok {
+ items[i].kind = cast(CompletionItemKind)symbol.type;
+ }
+
+
+ }
+
+ list.items = items[:];
}
+
+
return list, true;
}
@@ -1176,6 +1229,7 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP
case Bad_Expr:
if position_context.hint == .Completion && position_context.file.src[max(0, node.end.offset-1)] == '.' {
+
str := position_context.file.src[node.pos.offset:max(0, node.end.offset-1)];
p := parser.default_parser();
@@ -1186,13 +1240,12 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP
//do we still have recursive dots?
if strings.contains(string(str), ".") {
- e := parser.parse_expr(&p, true); //MEMORY LEAK - need to modify parser to allow for temp allocator
+ e := parser.parse_expr(&p, true);
position_context.selector = e;
}
else {
- //this might not hold be enough in the future
- e := parser.parse_ident(&p); //MEMORY LEAK - need to modify parser to allow for temp allocator
+ e := parser.parse_ident(&p);
position_context.selector = e;
}
diff --git a/src/server/documents.odin b/src/server/documents.odin
index 35c0940..3d08766 100644
--- a/src/server/documents.odin
+++ b/src/server/documents.odin
@@ -8,6 +8,7 @@ import "core:odin/parser"
import "core:odin/ast"
import "core:odin/tokenizer"
import "core:path"
+import "core:mem"
import "shared:common"
@@ -42,6 +43,9 @@ DocumentStorage :: struct {
document_storage: DocumentStorage;
+document_storage_shutdown :: proc() {
+ delete(document_storage.documents);
+}
document_get :: proc(uri_string: string) -> ^Document {
@@ -55,18 +59,12 @@ document_get :: proc(uri_string: string) -> ^Document {
}
/*
- Note(Daniel, Should there be reference counting of documents or just clear everything on workspace change?
- You usually always need the documents that are loaded in core files, your own files, etc.)
- */
-
-
-/*
Client opens a document with transferred text
*/
document_open :: proc(uri_string: string, text: string, config: ^common.Config, writer: ^Writer) -> common.Error {
- uri, parsed_ok := common.parse_uri(uri_string);
+ uri, parsed_ok := common.parse_uri(uri_string, context.allocator);
log.infof("document_open: %v", uri_string);
@@ -87,7 +85,7 @@ document_open :: proc(uri_string: string, text: string, config: ^common.Config,
document.text = transmute([] u8)text;
document.used_text = len(document.text);
- if err := document_refresh(document, config, writer, true); err != .None {
+ if err := document_refresh(document, config, writer); err != .None {
return err;
}
@@ -102,7 +100,7 @@ document_open :: proc(uri_string: string, text: string, config: ^common.Config,
used_text = len(text),
};
- if err := document_refresh(&document, config, writer, true); err != .None {
+ if err := document_refresh(&document, config, writer); err != .None {
return err;
}
@@ -203,11 +201,13 @@ document_apply_changes :: proc(uri_string: string, changes: [dynamic] TextDocume
//log.info(string(document.text[:document.used_text]));
- return document_refresh(document, config, writer, true);
+ return document_refresh(document, config, writer);
}
document_close :: proc(uri_string: string) -> common.Error {
+ log.infof("document_close: %v", uri_string);
+
uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator);
if !parsed_ok {
@@ -223,21 +223,18 @@ document_close :: proc(uri_string: string) -> common.Error {
document.client_owned = false;
- common.free_ast_file(document.ast);
-
common.delete_uri(document.uri);
delete(document.text);
document.used_text = 0;
-
return .None;
}
-document_refresh :: proc(document: ^Document, config: ^common.Config, writer: ^Writer, parse_imports: bool) -> common.Error {
+document_refresh :: proc(document: ^Document, config: ^common.Config, writer: ^Writer) -> common.Error {
errors, ok := parse_document(document, config);
@@ -323,6 +320,8 @@ parser_warning_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) {
parse_document :: proc(document: ^Document, config: ^common.Config) -> ([] ParserError, bool) {
+ context.allocator = context.temp_allocator;
+
p := parser.Parser {
err = parser_error_handler,
warn = parser_warning_handler,
@@ -335,21 +334,10 @@ parse_document :: proc(document: ^Document, config: ^common.Config) -> ([] Parse
src = document.text[:document.used_text],
};
- common.free_ast_file(document.ast);
-
parser.parse_file(&p, &document.ast);
- if document.imports != nil {
-
- for p in document.imports {
- delete(p.name);
- }
-
- delete(document.imports);
- }
-
document.imports = make([]Package, len(document.ast.imports));
- document.package_name = path.dir(document.uri.path, context.allocator); //todo(memory leak)
+ document.package_name = path.dir(document.uri.path, context.temp_allocator);
for imp, index in document.ast.imports {
@@ -367,9 +355,8 @@ parse_document :: proc(document: ^Document, config: ^common.Config) -> ([] Parse
continue;
}
- document.imports[index].name = path.join(dir, p);
+ document.imports[index].name = strings.clone(path.join(elems = {dir, p}, allocator = context.temp_allocator));
document.imports[index].base = path.base(document.imports[index].name, false);
-
}
//relative
@@ -379,7 +366,5 @@ parse_document :: proc(document: ^Document, config: ^common.Config) -> ([] Parse
}
- //fmt.println(document.imports);
-
return current_errors[:], true;
}
diff --git a/src/server/requests.odin b/src/server/requests.odin
index e5cf22b..45f252f 100644
--- a/src/server/requests.odin
+++ b/src/server/requests.odin
@@ -65,14 +65,14 @@ read_and_parse_header :: proc(reader: ^Reader) -> (Header, bool) {
break;
}
- index := strings.last_index_byte (message, ':');
+ index := strings.last_index_byte(message, ':');
if index == -1 {
log.error("Failed to find semicolon");
return header, false;
}
- header_name := message[0 : index];
+ header_name := message[0:index];
header_value := message[len(header_name) + 2 : len(message)-1];
if strings.compare(header_name, "Content-Length") == 0 {
@@ -131,6 +131,19 @@ read_and_parse_body :: proc(reader: ^Reader, header: Header) -> (json.Value, boo
}
+call_map : map [string] proc(json.Value, RequestId, ^common.Config, ^Writer) -> common.Error =
+ {"initialize" = request_initialize,
+ "initialized" = request_initialized,
+ "shutdown" = request_shutdown,
+ "exit" = notification_exit,
+ "textDocument/didOpen" = notification_did_open,
+ "textDocument/didChange" = notification_did_change,
+ "textDocument/didClose" = notification_did_close,
+ "textDocument/didSave" = notification_did_save,
+ "textDocument/definition" = request_definition,
+ "textDocument/completion" = request_completion,
+ "textDocument/signatureHelp" = request_signature_help};
+
handle_request :: proc(request: json.Value, config: ^common.Config, writer: ^Writer) -> bool {
root, ok := request.value.(json.Object);
@@ -158,19 +171,6 @@ handle_request :: proc(request: json.Value, config: ^common.Config, writer: ^Wri
method := root["method"].value.(json.String);
- call_map : map [string] proc(json.Value, RequestId, ^common.Config, ^Writer) -> common.Error =
- {"initialize" = request_initialize,
- "initialized" = request_initialized,
- "shutdown" = request_shutdown,
- "exit" = notification_exit,
- "textDocument/didOpen" = notification_did_open,
- "textDocument/didChange" = notification_did_change,
- "textDocument/didClose" = notification_did_close,
- "textDocument/didSave" = notification_did_save,
- "textDocument/definition" = request_definition,
- "textDocument/completion" = request_completion,
- "textDocument/signatureHelp" = request_signature_help};
-
fn: proc(json.Value, RequestId, ^common.Config, ^Writer) -> common.Error;
fn, ok = call_map[method];
@@ -198,6 +198,7 @@ handle_request :: proc(request: json.Value, config: ^common.Config, writer: ^Wri
}
}
+
return true;
}
@@ -295,6 +296,8 @@ request_definition :: proc(params: json.Value, id: RequestId, config: ^common.Co
return .InternalError;
}
+ document_refresh(document, config, writer);
+
location, ok2 := get_definition_location(document, definition_params.position);
if !ok2 {
@@ -324,18 +327,20 @@ request_completion :: proc(params: json.Value, id: RequestId, config: ^common.Co
completition_params: CompletionParams;
+
if unmarshal(params, completition_params, context.temp_allocator) != .None {
log.error("Failed to unmarshal completion request");
return .ParseError;
}
-
document := document_get(completition_params.textDocument.uri);
if document == nil {
return .InternalError;
}
+ document_refresh(document, config, writer);
+
list: CompletionList;
list, ok = get_completion_list(document, completition_params.position);
@@ -373,6 +378,8 @@ request_signature_help :: proc(params: json.Value, id: RequestId, config: ^commo
return .InternalError;
}
+ document_refresh(document, config, writer);
+
help: SignatureHelp;
help, ok = get_signature_information(document, signature_params.position);
@@ -424,6 +431,7 @@ notification_did_change :: proc(params: json.Value, id: RequestId, config: ^comm
return .ParseError;
}
+
document_apply_changes(change_params.textDocument.uri, change_params.contentChanges, config, writer);
return .None;
diff --git a/src/server/unmarshal.odin b/src/server/unmarshal.odin
index 828e62c..908f83c 100644
--- a/src/server/unmarshal.odin
+++ b/src/server/unmarshal.odin
@@ -12,7 +12,7 @@ import "core:fmt"
Right now union handling is type specific so you can only have one struct type, int type, etc.
*/
-unmarshal :: proc(json_value: json.Value, v: any, allocator := context.allocator) -> json.Marshal_Error {
+unmarshal :: proc(json_value: json.Value, v: any, allocator: mem.Allocator) -> json.Marshal_Error {
using runtime;
@@ -52,7 +52,7 @@ unmarshal :: proc(json_value: json.Value, v: any, allocator := context.allocator
id := variant.variants[0].id;
- unmarshal(json_value, any{v.data, id});
+ unmarshal(json_value, any{v.data, id}, allocator);
}
case json.Array: