From 64c5d8dffb25cf612807434dc84d3d37c876ba8e Mon Sep 17 00:00:00 2001 From: DanielGavin Date: Fri, 29 Jan 2021 02:24:40 +0100 Subject: use the dynamic indexer to index on save --- src/index/indexer.odin | 32 ++++++++++++++++++- src/server/requests.odin | 83 ++++++++++++++++++++++++++++++++++++++++++++++-- src/server/types.odin | 10 ++++++ 3 files changed, 121 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/index/indexer.odin b/src/index/indexer.odin index 1ad2b8b..591a440 100644 --- a/src/index/indexer.odin +++ b/src/index/indexer.odin @@ -76,7 +76,37 @@ lookup :: proc(name: string, pkg: string, loc := #caller_location) -> (Symbol, b fuzzy_search :: proc(name: string, pkgs: [] string) -> ([] FuzzyResult, bool) { - return memory_index_fuzzy_search(&indexer.static_index, name, pkgs); + dynamic_results, dynamic_ok := memory_index_fuzzy_search(&indexer.dynamic_index, name, pkgs); + index_results, static_ok := memory_index_fuzzy_search(&indexer.static_index, name, pkgs); + result := make([dynamic] FuzzyResult, context.temp_allocator); + + if !dynamic_ok || !static_ok { + return {}, false; + } + + for r in dynamic_results { + append(&result, r); + } + + for r in index_results { + append(&result, r); + } + + sort.sort(fuzzy_sort_interface(&result)); + + name := ""; + pkg := ""; + + for r, i in result { + if name == r.symbol.name && pkg == r.symbol.pkg { + ordered_remove(&result, i); + } + + name = r.symbol.name; + pkg = r.symbol.pkg; + } + + return result[:], true; } diff --git a/src/server/requests.odin b/src/server/requests.odin index a172e98..aeaddf8 100644 --- a/src/server/requests.odin +++ b/src/server/requests.odin @@ -14,6 +14,8 @@ import "core:thread" import "core:sync" import "core:path/filepath" import "intrinsics" +import "core:odin/ast" +import "core:odin/parser" import "shared:common" import "shared:index" @@ -323,7 +325,7 @@ handle_request :: proc(request: json.Value, config: ^common.Config, writer: ^Wri task_proc(&task); - case .DidClose, .DidChange, .DidOpen: + case .DidClose, .DidChange, .DidOpen, .DidSave: uri := root["params"].value.(json.Object)["textDocument"].value.(json.Object)["uri"].value.(json.String); @@ -501,6 +503,9 @@ request_initialize :: proc(task: ^common.Task) { textDocumentSync = TextDocumentSyncOptions { openClose = true, change = 2, //incremental + save = { + includeText = true, + } }, definitionProvider = true, completionProvider = CompletionOptions { @@ -531,6 +536,8 @@ request_initialize :: proc(task: ^common.Task) { Temp index here, but should be some background thread that starts the indexing */ + index.indexer.dynamic_index = index.make_memory_index(index.make_symbol_collection(context.allocator, config)); + index.build_static_index(context.allocator, config); /* @@ -790,8 +797,78 @@ notification_did_save :: proc(task: ^common.Task) { using info; - json.destroy_value(root); - free(info); + + defer json.destroy_value(root); + defer free(info); + + //this is temporary, but will provide dynamic indexing and is syncronized + + params_object, ok := params.value.(json.Object); + + if !ok { + handle_error(.ParseError, id, writer); + return; + } + + save_params: DidSaveTextDocumentParams; + + if unmarshal(params, save_params, context.temp_allocator) != .None { + handle_error(.ParseError, id, writer); + return; + } + + uri: common.Uri; + + if uri, ok = common.parse_uri(save_params.textDocument.uri, context.temp_allocator); !ok { + handle_error(.ParseError, id, writer); + return; + } + + fullpath := uri.path; + + p := parser.Parser { + err = index.log_error_handler, + warn = index.log_warning_handler, + }; + + //have to cheat the parser since it really wants to parse an entire package with the new changes... + dir := filepath.base(filepath.dir(fullpath, context.temp_allocator)); + + pkg := new(ast.Package); + pkg.kind = .Normal; + pkg.fullpath = fullpath; + pkg.name = dir; + + if dir == "runtime" { + pkg.kind = .Runtime; + } + + file := ast.File { + fullpath = fullpath, + src = transmute([]u8)save_params.text, + pkg = pkg, + }; + + ok = parser.parse_file(&p, &file); + + if !ok { + log.errorf("error in parse file for indexing %v", fullpath); + } + + for key, value in index.indexer.dynamic_index.collection.symbols { + + if value.uri == save_params.textDocument.uri { + index.free_symbol(value, context.allocator); + index.indexer.dynamic_index.collection.symbols[key] = {}; + } + + } + + if ret := index.collect_symbols(&index.indexer.dynamic_index.collection, file, uri.uri); ret != .None { + log.errorf("failed to collect symbols on save %v", ret); + } + + //log.error(index.indexer.dynamic_index.collection.symbols); } request_semantic_token_full :: proc(task: ^common.Task) { diff --git a/src/server/types.odin b/src/server/types.odin index 4ddf089..a9d8983 100644 --- a/src/server/types.odin +++ b/src/server/types.odin @@ -94,6 +94,10 @@ CompletionOptions :: struct { triggerCharacters: [] string, }; +SaveOptions :: struct { + includeText: bool, +} + HoverClientCapabilities :: struct { dynamicRegistration: bool, contentFormat: [dynamic] string, @@ -200,6 +204,11 @@ DidCloseTextDocumentParams :: struct { textDocument: TextDocumentIdentifier, }; +DidSaveTextDocumentParams :: struct { + textDocument: TextDocumentIdentifier, + text: string, +}; + TextDocumentPositionParams :: struct { textDocument: TextDocumentIdentifier, position: common.Position, @@ -258,6 +267,7 @@ CompletionList :: struct { TextDocumentSyncOptions :: struct { openClose: bool, change: int, + save: SaveOptions, }; SignatureHelp :: struct { -- cgit v1.2.3