diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2020-11-18 22:14:33 +0100 |
|---|---|---|
| committer | DanielGavin <danielgavin5@hotmail.com> | 2020-11-18 22:14:33 +0100 |
| commit | 3370a5e546ea9355068ba99b5e81f80527d2e582 (patch) | |
| tree | 5a93eda4e2a5be4ec58d3ddf2595fa7dc1016cb3 /src/server | |
| parent | ee4a7f64bcb9d6d7b60d5495fc072b2a62b5f790 (diff) | |
fixed all the memory leaks
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/analysis.odin | 77 | ||||
| -rw-r--r-- | src/server/documents.odin | 45 | ||||
| -rw-r--r-- | src/server/requests.odin | 40 | ||||
| -rw-r--r-- | src/server/unmarshal.odin | 4 |
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: |