aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2022-01-19 23:44:50 +0100
committerDaniel Gavin <danielgavin5@hotmail.com>2022-01-19 23:44:50 +0100
commit989345d0438429ae719287f9c7343f87b558f7e3 (patch)
treefa789c8e61dcc53d7cffc7f2485770a5026abdc8 /src/server
parent329180066047e6dd802872104af5be2955f092cf (diff)
Remove the failed idea of making request tasks
Diffstat (limited to 'src/server')
-rw-r--r--src/server/caches.odin19
-rw-r--r--src/server/completion.odin2
-rw-r--r--src/server/definition.odin2
-rw-r--r--src/server/document_symbols.odin2
-rw-r--r--src/server/documents.odin12
-rw-r--r--src/server/hover.odin2
-rw-r--r--src/server/inlay_hints.odin20
-rw-r--r--src/server/lens.odin2
-rw-r--r--src/server/requests.odin635
-rw-r--r--src/server/semantic_tokens.odin98
-rw-r--r--src/server/signature.odin2
-rw-r--r--src/server/types.odin6
12 files changed, 311 insertions, 491 deletions
diff --git a/src/server/caches.odin b/src/server/caches.odin
new file mode 100644
index 0000000..640677f
--- /dev/null
+++ b/src/server/caches.odin
@@ -0,0 +1,19 @@
+package server
+
+import "shared:index"
+import "shared:analysis"
+import "shared:common"
+
+//Used in semantic tokens and inlay hints to handle the entire file being resolved.
+FileResolveCache :: struct {
+ files: map[string]map[uintptr]index.Symbol,
+}
+
+file_resolve_cache: FileResolveCache
+
+resolve_entire_file :: proc(document: ^common.Document) {
+ file_resolve_cache.files[document.uri.uri] = analysis.resolve_entire_file(
+ document,
+ common.scratch_allocator(document.allocator),
+ )
+}
diff --git a/src/server/completion.odin b/src/server/completion.odin
index e869006..6b24d9d 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -49,7 +49,7 @@ get_completion_list :: proc(document: ^common.Document, position: common.Positio
return list, true;
}
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
get_globals(document.ast, &ast_context);
diff --git a/src/server/definition.odin b/src/server/definition.odin
index 52e09dd..116fbd9 100644
--- a/src/server/definition.odin
+++ b/src/server/definition.odin
@@ -26,7 +26,7 @@ get_definition_location :: proc(document: ^common.Document, position: common.Pos
location: common.Location;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
uri: string;
diff --git a/src/server/document_symbols.odin b/src/server/document_symbols.odin
index 3d3a296..7105465 100644
--- a/src/server/document_symbols.odin
+++ b/src/server/document_symbols.odin
@@ -23,7 +23,7 @@ import "shared:analysis"
get_document_symbols :: proc(document: ^common.Document) -> []DocumentSymbol {
using analysis;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
get_globals(document.ast, &ast_context);
diff --git a/src/server/documents.odin b/src/server/documents.odin
index 94c0cd6..4f5610a 100644
--- a/src/server/documents.odin
+++ b/src/server/documents.odin
@@ -23,7 +23,7 @@ ParserError :: struct {
}
DocumentStorage :: struct {
- documents: map[string] common.Document,
+ documents: map[string]common.Document,
free_allocators: [dynamic]^common.Scratch_Allocator,
}
@@ -224,8 +224,8 @@ document_close :: proc(uri_string: string) -> common.Error {
free_all(common.scratch_allocator(document.allocator));
document_free_allocator(document.allocator);
- document.allocator = nil;
+ document.allocator = nil;
document.client_owned = false;
common.delete_uri(document.uri);
@@ -298,6 +298,12 @@ document_refresh :: proc(document: ^common.Document, config: ^common.Config, wri
}
}
+ //We only resolve the entire file, if we are dealing with the heavy features that require the entire file resolved.
+ //This gives the user a choice to use "fast mode" with only completion and gotos.
+ if config.enable_semantic_tokens || config.enable_inlay_hints {
+ resolve_entire_file(document);
+ }
+
return .None;
}
@@ -324,8 +330,6 @@ parse_document :: proc(document: ^common.Document, config: ^common.Config) -> ([
context.allocator = common.scratch_allocator(document.allocator);
- document.symbol_cache = make(map[int]rawptr, 10, common.scratch_allocator(document.allocator));
-
//have to cheat the parser since it really wants to parse an entire package with the new changes...
pkg := new(ast.Package);
pkg.kind = .Normal;
diff --git a/src/server/hover.odin b/src/server/hover.odin
index 1a45b8c..e7c5dba 100644
--- a/src/server/hover.odin
+++ b/src/server/hover.odin
@@ -57,7 +57,7 @@ get_hover_information :: proc(document: ^common.Document, position: common.Posit
},
};
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
position_context, ok := get_document_position_context(document, position, .Hover);
diff --git a/src/server/inlay_hints.odin b/src/server/inlay_hints.odin
index e67aac9..1e7d2c3 100644
--- a/src/server/inlay_hints.odin
+++ b/src/server/inlay_hints.odin
@@ -8,20 +8,19 @@ import "shared:analysis"
import "shared:index"
//document
-get_inlay_hints :: proc(document: ^common.Document) -> ([]InlayHint, bool) {
-
+get_inlay_hints :: proc(document: ^common.Document, symbols: map[uintptr]index.Symbol) -> ([]InlayHint, bool) {
using analysis;
hints := make([dynamic]InlayHint, context.temp_allocator);
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
Visit_Data :: struct {
- calls: [dynamic]ast.Call_Expr,
+ calls: [dynamic]^ast.Node,
}
data := Visit_Data {
- calls = make([dynamic]ast.Call_Expr, context.temp_allocator),
+ calls = make([dynamic]^ast.Node, context.temp_allocator),
};
visit :: proc(visitor: ^ast.Visitor, node: ^ast.Node) -> ^ast.Visitor {
@@ -32,7 +31,7 @@ get_inlay_hints :: proc(document: ^common.Document) -> ([]InlayHint, bool) {
data := cast(^Visit_Data)visitor.data;
if call, ok := node.derived.(ast.Call_Expr); ok {
- append(&data.calls, call);
+ append(&data.calls, node);
}
return visitor;
@@ -47,15 +46,18 @@ get_inlay_hints :: proc(document: ^common.Document) -> ([]InlayHint, bool) {
ast.walk(&visitor, decl);
}
- loop: for call in &data.calls {
+ loop: for node_call in &data.calls {
symbol_arg_count := 0
+
+ call := node_call.derived.(ast.Call_Expr);
+
for arg in call.args {
if _, ok := arg.derived.(ast.Field); ok {
continue loop;
}
}
- if symbol, ok := resolve_type_expression(&ast_context, &call); ok {
+ if symbol, ok := symbols[cast(uintptr)node_call]; ok {
if symbol_call, ok := symbol.value.(index.SymbolProcedureValue); ok {
for arg in symbol_call.arg_types {
for name in arg.names {
@@ -66,7 +68,7 @@ get_inlay_hints :: proc(document: ^common.Document) -> ([]InlayHint, bool) {
if ident, ok := name.derived.(ast.Ident); ok {
hint := InlayHint {
kind = "parameter",
- label = fmt.tprintf("%v:", ident.name),
+ label = fmt.tprintf("%v = ", ident.name),
range = common.get_token_range(call.args[symbol_arg_count], string(document.text)),
}
append(&hints, hint);
diff --git a/src/server/lens.odin b/src/server/lens.odin
index 822a115..9d80d0c 100644
--- a/src/server/lens.odin
+++ b/src/server/lens.odin
@@ -24,7 +24,7 @@ get_code_lenses :: proc(document: ^common.Document, position: common.Position) -
using analysis;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
get_globals(document.ast, &ast_context);
diff --git a/src/server/requests.odin b/src/server/requests.odin
index 4fc4b48..5ab8dde 100644
--- a/src/server/requests.odin
+++ b/src/server/requests.odin
@@ -56,11 +56,6 @@ RequestInfo :: struct {
result: common.Error,
}
-pool: common.Pool;
-
-get_request_info :: proc (task: ^common.Task) -> ^RequestInfo {
- return cast(^RequestInfo)task.data;
-}
make_response_message :: proc (id: RequestId, params: ResponseParams) -> ResponseMessage {
@@ -159,7 +154,7 @@ read_and_parse_body :: proc (reader: ^Reader, header: Header) -> (json.Value, bo
err: json.Error;
- value, err = json.parse(data = data, allocator = context.allocator, parse_integers = true);
+ value, err = json.parse(data = data, allocator = context.temp_allocator, parse_integers = true);
if (err != json.Error.None) {
log.error("Failed to parse body");
@@ -169,41 +164,27 @@ read_and_parse_body :: proc (reader: ^Reader, header: Header) -> (json.Value, bo
return value, true;
}
-request_map: map[string]RequestType = {
- "initialize" = .Initialize,
- "initialized" = .Initialized,
- "shutdown" = .Shutdown,
- "exit" = .Exit,
- "textDocument/didOpen" = .DidOpen,
- "textDocument/didChange" = .DidChange,
- "textDocument/didClose" = .DidClose,
- "textDocument/didSave" = .DidSave,
- "textDocument/definition" = .Definition,
- "textDocument/completion" = .Completion,
- "textDocument/signatureHelp" = .SignatureHelp,
- "textDocument/documentSymbol" = .DocumentSymbol,
- "textDocument/semanticTokens/full" = .SemanticTokensFull,
- "textDocument/semanticTokens/range" = .SemanticTokensRange,
- "textDocument/hover" = .Hover,
- "$/cancelRequest" = .CancelRequest,
- "textDocument/formatting" = .FormatDocument,
- "odin/inlayHints" = .InlayHint,
+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,
+ "textDocument/documentSymbol" = request_document_symbols,
+ "textDocument/semanticTokens/full" = request_semantic_token_full,
+ "textDocument/semanticTokens/range" = request_semantic_token_range,
+ "textDocument/hover" = request_hover,
+ "textDocument/formatting" = request_format_document,
};
-handle_error :: proc (err: common.Error, id: RequestId, writer: ^Writer) {
-
- if err != .None {
-
- response := make_response_message_error(
- id = id,
- error = ResponseError {code = err, message = ""});
-
- send_error(response, writer);
- }
-}
-
handle_request :: proc (request: json.Value, config: ^common.Config, writer: ^Writer) -> bool {
-
root, ok := request.(json.Object);
if !ok {
@@ -229,8 +210,8 @@ handle_request :: proc (request: json.Value, config: ^common.Config, writer: ^Wr
method := root["method"].(json.String);
- request_type: RequestType;
- request_type, ok = request_map[method];
+ fn: proc(json.Value, RequestId, ^common.Config, ^Writer) -> common.Error;
+ fn, ok = call_map[method];
if !ok {
response := make_response_message_error(
@@ -239,157 +220,31 @@ handle_request :: proc (request: json.Value, config: ^common.Config, writer: ^Wr
send_error(response, writer);
} else {
-
- info := new(RequestInfo);
-
- info.root = request;
- info.params = root["params"];
- info.id = id;
- info.config = config;
- info.writer = writer;
-
- task_proc: common.Task_Proc;
-
- switch request_type {
- case .Initialize:
- task_proc = request_initialize;
- case .Initialized:
- task_proc = request_initialized;
- case .Shutdown:
- task_proc = request_shutdown;
- case .Exit:
- task_proc = notification_exit;
- case .DidOpen:
- task_proc = notification_did_open;
- case .DidChange:
- task_proc = notification_did_change;
- case .DidClose:
- task_proc = notification_did_close;
- case .DidSave:
- task_proc = notification_did_save;
- case .Definition:
- task_proc = request_definition;
- case .Completion:
- task_proc = request_completion;
- case .SignatureHelp:
- task_proc = request_signature_help;
- case .DocumentSymbol:
- task_proc = request_document_symbols;
- case .SemanticTokensFull:
- task_proc = request_semantic_token_full;
- case .SemanticTokensRange:
- task_proc = request_semantic_token_range;
- case .Hover:
- task_proc = request_hover;
- case .CancelRequest:
- case .FormatDocument:
- task_proc = request_format_document;
- case .InlayHint:
- task_proc = request_inlay_hint;
- }
-
- task := common.Task {
- data = info,
- procedure = task_proc,
- };
-
- #partial switch request_type {
- case .CancelRequest:
- for {
- if task, ok := common.pool_try_and_pop_task(&pool); ok {
- common.pool_do_work(&pool, &task);
- } else {
- break;
- }
- }
- case .Initialize, .Initialized:
- task_proc(&task);
- case .Completion, .Definition, .Hover, .FormatDocument:
-
- uri := root["params"].(json.Object)["textDocument"].(json.Object)["uri"].(json.String);
-
- document := document_get(uri);
-
- if document == nil {
- handle_error(.InternalError, id, writer);
- return false;
- }
-
- info.document = document;
-
- task_proc(&task);
-
- case .DidClose, .DidChange, .DidOpen, .DidSave:
-
- uri := root["params"].(json.Object)["textDocument"].(json.Object)["uri"].(json.String);
-
- document := document_get(uri);
-
- if document != nil {
-
- for intrinsics.atomic_load(&document.operating_on) > 1 {
- if task, ok := common.pool_try_and_pop_task(&pool); ok {
- common.pool_do_work(&pool, &task);
- }
- }
- }
-
- task_proc(&task);
-
- document_release(document);
- case .Shutdown,.Exit:
- task_proc(&task);
- case .SignatureHelp, .SemanticTokensFull, .SemanticTokensRange, .DocumentSymbol, .InlayHint:
-
- uri := root["params"].(json.Object)["textDocument"].(json.Object)["uri"].(json.String);
-
- document := document_get(uri);
-
- if document == nil {
- handle_error(.InternalError, id, writer);
- return false;
- }
-
- info.document = document;
-
- if !config.debug_single_thread {
- common.pool_add_task(&pool, task_proc, info);
- } else {
- task_proc(&task);
- }
- case:
-
- if !config.debug_single_thread {
- common.pool_add_task(&pool, task_proc, info);
- } else {
- task_proc(&task);
- }
- }
+ err := fn(root["params"], id, config, writer);
+ if err != .None {
+ response := make_response_message_error(
+ id = id,
+ error = ResponseError {code = err, message = ""},
+ );
+ send_error(response, writer);
+ }
}
return true;
}
-request_initialize :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
+request_initialize :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
- defer free(info);
- defer json.destroy_value(info.root);
-
params_object, ok := params.(json.Object);
-
- if !ok {
- handle_error(.ParseError, id, writer);
- return;
- }
+
+ if !ok {
+ return .ParseError;
+ }
initialize_params: RequestInitializeParams;
if unmarshal(params, initialize_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
config.workspace_folders = make([dynamic]common.WorkspaceFolder);
@@ -424,6 +279,7 @@ request_initialize :: proc (task: ^common.Task) {
config.formatter = ols_config.formatter;
config.odin_command = strings.clone(ols_config.odin_command, context.allocator);
config.checker_args = ols_config.checker_args;
+ config.enable_inlay_hints = ols_config.enable_inlay_hints;
for p in ols_config.collections {
@@ -479,8 +335,6 @@ request_initialize :: proc (task: ^common.Task) {
config.collections["vendor"] = path.join(elems = {forward_path, "vendor"}, allocator = context.allocator);
}
- common.pool_init(&pool, config.thread_count);
- common.pool_start(&pool);
for format in initialize_params.capabilities.textDocument.hover.contentFormat {
if format == "markdown" {
@@ -578,58 +432,40 @@ request_initialize :: proc (task: ^common.Task) {
}
log.info("Finished indexing");
-}
-
-request_initialized :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
- json.destroy_value(root);
- free(info);
+ return .None;
}
-request_shutdown :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
-
- defer {
- json.destroy_value(root);
- free(info);
- }
-
- response := make_response_message(
- params = nil,
- id = id);
-
- send_response(response, writer);
+request_initialized :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
+ return .None;
}
-request_definition :: proc (task: ^common.Task) {
- info := get_request_info(task);
+request_shutdown :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
+ response := make_response_message(params = nil, id = id);
- using info;
+ send_response(response, writer);
- defer {
- document_release(document);
- json.destroy_value(root);
- free(info);
- }
+ return .None;
+}
+request_definition :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
definition_params: TextDocumentPositionParams;
if unmarshal(params, definition_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
+
+ document := document_get(definition_params.textDocument.uri);
+
+ if document == nil {
+ return .InternalError;
+ }
locations, ok2 := get_definition_location(document, definition_params.position);
@@ -644,260 +480,192 @@ request_definition :: proc (task: ^common.Task) {
response := make_response_message(params = locations, id = id);
send_response(response, writer);
}
-}
-
-request_completion :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
- defer {
- document_release(document);
- json.destroy_value(root);
- free(info);
- }
+ return .None;
+}
+request_completion :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
completition_params: CompletionParams;
if unmarshal(params, completition_params, context.temp_allocator) != .None {
log.error("Failed to unmarshal completion request");
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
- //context.allocator = common.scratch_allocator(document.allocator);
+ document := document_get(completition_params.textDocument.uri);
+
+ if document == nil {
+ return .InternalError;
+ }
list: CompletionList;
list, ok = get_completion_list(document, completition_params.position, completition_params.context_);
if !ok {
- handle_error(.InternalError, id, writer);
- return;
+ return .InternalError;
}
- response := make_response_message(
- params = list,
- id = id);
+ response := make_response_message(params = list, id = id);
send_response(response, writer);
-}
-
-request_signature_help :: proc (task: ^common.Task) {
- info := get_request_info(task);
- using info;
-
- defer {
- document_release(document);
- json.destroy_value(root);
- free(info);
- }
+ return .None;
+}
+request_signature_help :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
signature_params: SignatureHelpParams;
if unmarshal(params, signature_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
+ document := document_get(signature_params.textDocument.uri);
+
+ if document == nil {
+ return .InternalError;
+ }
+
help: SignatureHelp;
help, ok = get_signature_information(document, signature_params.position);
if !ok {
- handle_error(.InternalError, id, writer);
- return;
+ return .InternalError;
}
- response := make_response_message(
- params = help,
- id = id);
+ response := make_response_message(params = help, id = id);
send_response(response, writer);
-}
-request_format_document :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
-
- defer {
- document_release(document);
- json.destroy_value(root);
- free(info);
- }
+ return .None;
+}
+request_format_document :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
format_params: DocumentFormattingParams;
if unmarshal(params, format_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
+ document := document_get(format_params.textDocument.uri);
+
+ if document == nil {
+ return .InternalError;
+ }
+
edit: []TextEdit;
edit, ok = get_complete_format(document, config);
if !ok {
- handle_error(.InternalError, id, writer);
- return;
+ return .InternalError;
}
- response := make_response_message(
- params = edit,
- id = id);
+ response := make_response_message(params = edit, id = id);
send_response(response, writer);
-}
-
-notification_exit :: proc (task: ^common.Task) {
- info := get_request_info(task);
- using info;
- defer {
- json.destroy_value(root);
- free(info);
- }
+ return .None;
+}
+notification_exit :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
config.running = false;
+ return .None;
}
-notification_did_open :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
-
- defer {
- json.destroy_value(root);
- free(info);
- }
-
+notification_did_open :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
log.error("Failed to parse open document notification");
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
open_params: DidOpenTextDocumentParams;
if unmarshal(params, open_params, context.allocator) != .None {
log.error("Failed to parse open document notification");
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
if n := document_open(open_params.textDocument.uri, open_params.textDocument.text, config, writer); n != .None {
- handle_error(n, id, writer);
+ return .InternalError;
}
-}
-
-notification_did_change :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
- defer {
- json.destroy_value(root);
- free(info);
- }
+ return .None;
+}
+notification_did_change :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
change_params: DidChangeTextDocumentParams;
if unmarshal(params, change_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
document_apply_changes(change_params.textDocument.uri, change_params.contentChanges, config, writer);
-}
-notification_did_close :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
-
- defer {
- json.destroy_value(root);
- free(info);
- }
+ return .None;
+}
+notification_did_close :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
close_params: DidCloseTextDocumentParams;
if unmarshal(params, close_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
if n := document_close(close_params.textDocument.uri); n != .None {
- handle_error(n, id, writer);
- return;
+ return .InternalError;
}
-}
-
-notification_did_save :: proc (task: ^common.Task) {
- info := get_request_info(task);
- using info;
-
- defer {
- json.destroy_value(root);
- free(info);
- }
+ return .None;
+}
+notification_did_save :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
save_params: DidSaveTextDocumentParams;
if unmarshal(params, save_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
uri: common.Uri;
if uri, ok = common.parse_uri(save_params.textDocument.uri, context.temp_allocator); !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
fullpath := uri.path;
@@ -942,34 +710,29 @@ notification_did_save :: proc (task: ^common.Task) {
}
check(uri, writer, config);
-}
-
-request_semantic_token_full :: proc (task: ^common.Task) {
- info := get_request_info(task);
- using info;
-
- defer {
- document_release(document);
- json.destroy_value(root);
- free(info);
-
- }
+ return .None;
+}
+request_semantic_token_full :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
semantic_params: SemanticTokensParams;
if unmarshal(params, semantic_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
+ document := document_get(semantic_params.textDocument.uri);
+
+ if document == nil {
+ return .InternalError;
+ }
+
range := common.Range {
start = common.Position {
line = 0,
@@ -982,155 +745,145 @@ request_semantic_token_full :: proc (task: ^common.Task) {
symbols: SemanticTokens;
if config.enable_semantic_tokens {
- symbols = get_semantic_tokens(document, range);
+ if cache_symbols, ok := file_resolve_cache.files[document.uri.uri]; ok {
+ symbols = get_semantic_tokens(document, range, cache_symbols);
+ }
}
- response := make_response_message(
- params = symbols,
- id = id);
+ response := make_response_message(params = symbols, id = id);
send_response(response, writer);
-}
-
-request_semantic_token_range :: proc (task: ^common.Task) {
- info := get_request_info(task);
- using info;
+ return .None;
+}
+request_semantic_token_range :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
- defer {
- document_release(document);
- json.destroy_value(root);
- free(info);
- }
-
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .None;
}
semantic_params: SemanticTokensRangeParams;
if unmarshal(params, semantic_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .None;
}
+ document := document_get(semantic_params.textDocument.uri);
+
+ if document == nil {
+ return .InternalError;
+ }
+
symbols: SemanticTokens;
if config.enable_semantic_tokens {
- symbols = get_semantic_tokens(document, semantic_params.range);
+ if cache_symbols, ok := file_resolve_cache.files[document.uri.uri]; ok {
+ symbols = get_semantic_tokens(document, semantic_params.range, cache_symbols);
+ }
}
- response := make_response_message(
- params = symbols,
- id = id);
+ response := make_response_message(params = symbols, id = id);
send_response(response, writer);
-}
-
-request_document_symbols :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
- defer {
- document_release(document);
- json.destroy_value(root);
- free(info);
- }
+ return .None;
+}
+request_document_symbols :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
symbol_params: DocumentSymbolParams;
if unmarshal(params, symbol_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
+ document := document_get(symbol_params.textDocument.uri);
+
+ if document == nil {
+ return .InternalError;
+ }
+
symbols := get_document_symbols(document);
- response := make_response_message(
- params = symbols,
- id = id);
+ response := make_response_message(params = symbols, id = id);
send_response(response, writer);
-}
-request_hover :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
+ return .None;
+}
- defer {
- document_release(document);
- json.destroy_value(root);
- free(info);
- }
-
+request_hover :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
hover_params: HoverParams;
if unmarshal(params, hover_params, context.temp_allocator) != .None {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
}
+ document := document_get(hover_params.textDocument.uri);
+
+ if document == nil {
+ return .InternalError;
+ }
+
hover: Hover;
hover, ok = get_hover_information(document, hover_params.position);
if !ok {
- handle_error(.InternalError, id, writer);
- return;
+ return .InternalError;
}
- response := make_response_message(
- params = hover,
- id = id);
+ response := make_response_message(params = hover, id = id);
send_response(response, writer);
-}
-request_inlay_hint :: proc (task: ^common.Task) {
- info := get_request_info(task);
-
- using info;
+ return .None;
+}
- defer {
- document_release(document);
- json.destroy_value(root);
- free(info);
- }
-
+request_inlay_hint :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error {
params_object, ok := params.(json.Object);
if !ok {
- handle_error(.ParseError, id, writer);
- return;
+ return .ParseError;
+ }
+
+ inlay_params: InlayParams;
+
+ if unmarshal(params, inlay_params, context.temp_allocator) != .None {
+ return .ParseError;
}
+ document := document_get(inlay_params.textDocument.uri);
+
+ if document == nil {
+ return .InternalError;
+ }
+
hints: []InlayHint;
- hints, ok = get_inlay_hints(document);
+
+ if cache_symbols, ok := file_resolve_cache.files[document.uri.uri]; ok && config.enable_inlay_hints {
+ hints, ok = get_inlay_hints(document, cache_symbols);
+ }
if !ok {
- handle_error(.InternalError, id, writer);
- return;
+ return .InternalError;
}
response := make_response_message(params = hints, id = id);
send_response(response, writer);
+
+ return .None;
} \ No newline at end of file
diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin
index 095bb91..2977ddc 100644
--- a/src/server/semantic_tokens.odin
+++ b/src/server/semantic_tokens.odin
@@ -3,6 +3,7 @@ package server
import "core:odin/tokenizer"
import "core:odin/ast"
import "core:log"
+import "core:fmt"
import "shared:common"
import "shared:index"
@@ -32,11 +33,11 @@ SemanticTokenTypes :: enum {
Method,
}
-SemanticTokenModifiers :: enum {
- None,
- Declaration,
- Definition,
- Deprecated,
+SemanticTokenModifiers :: enum(u32) {
+ None = 0,
+ Declaration = 2,
+ Definition = 4,
+ Deprecated = 8,
}
SemanticTokensClientCapabilities :: struct {
@@ -77,6 +78,8 @@ SemanticTokens :: struct {
SemanticTokenBuilder :: struct {
current_start: int,
tokens: [dynamic]u32,
+ symbols: map[uintptr]index.Symbol,
+ selector: bool,
}
make_token_builder :: proc(allocator := context.temp_allocator) -> SemanticTokenBuilder {
@@ -91,7 +94,7 @@ get_tokens :: proc(builder: SemanticTokenBuilder) -> SemanticTokens {
};
}
-get_semantic_tokens :: proc(document: ^common.Document, range: common.Range) -> SemanticTokens {
+get_semantic_tokens :: proc(document: ^common.Document, range: common.Range, symbols: map[uintptr]index.Symbol) -> SemanticTokens {
using analysis;
builder := make_token_builder();
@@ -100,9 +103,9 @@ get_semantic_tokens :: proc(document: ^common.Document, range: common.Range) ->
write_semantic_token(&builder, document.ast.pkg_token, document.ast.src, .Keyword, .None);
}
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
- //resolve_entire_file(document, &ast_context, context.temp_allocator);
+ builder.symbols = symbols;
ast_context.current_package = ast_context.document_package;
@@ -118,19 +121,19 @@ get_semantic_tokens :: proc(document: ^common.Document, range: common.Range) ->
write_semantic_node :: proc(builder: ^SemanticTokenBuilder, node: ^ast.Node, src: string, type: SemanticTokenTypes, modifier: SemanticTokenModifiers) {
position := common.get_relative_token_position(node.pos.offset, transmute([]u8)src, builder.current_start);
name := common.get_ast_node_string(node, src);
- append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(name), cast(u32)type, 0);
+ append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(name), cast(u32)type, cast(u32)modifier);
builder.current_start = node.pos.offset;
}
write_semantic_token :: proc(builder: ^SemanticTokenBuilder, token: tokenizer.Token, src: string, type: SemanticTokenTypes, modifier: SemanticTokenModifiers) {
position := common.get_relative_token_position(token.pos.offset, transmute([]u8)src, builder.current_start);
- append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(token.text), cast(u32)type, 0);
+ append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(token.text), cast(u32)type, cast(u32)modifier);
builder.current_start = token.pos.offset;
}
write_semantic_string :: proc(builder: ^SemanticTokenBuilder, pos: tokenizer.Pos, name: string, src: string, type: SemanticTokenTypes, modifier: SemanticTokenModifiers) {
position := common.get_relative_token_position(pos.offset, transmute([]u8)src, builder.current_start);
- append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(name), cast(u32)type, 0);
+ append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(name), cast(u32)type, cast(u32)modifier);
builder.current_start = pos.offset;
}
@@ -169,11 +172,7 @@ visit_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context:
write_semantic_string(builder, node.pos, "..", ast_context.file.src, .Operator, .None);
visit(n.expr, builder, ast_context);
case Ident:
- if true {
- write_semantic_node(builder, node, ast_context.file.src, .Variable, .None);
- return;
- }
- if symbol, ok := analysis.lookup_symbol_cache(ast_context, n); ok {
+ if symbol, ok := builder.symbols[cast(uintptr)node]; ok {
if symbol.type == .Variable {
write_semantic_node(builder, node, ast_context.file.src, .Variable, .None);
}
@@ -195,6 +194,12 @@ visit_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context:
}
case Selector_Expr:
visit_selector(cast(^Selector_Expr)node, builder, ast_context);
+ builder.selector = false;
+ case When_Stmt:
+ write_semantic_string(builder, n.when_pos, "when", ast_context.file.src, .Keyword, .None);
+ visit(n.cond, builder, ast_context);
+ visit(n.body, builder, ast_context);
+ visit(n.else_stmt, builder, ast_context);
case Pointer_Type:
write_semantic_string(builder, node.pos, "^", ast_context.file.src, .Operator, .None);
visit(n.elem, builder, ast_context);
@@ -204,6 +209,12 @@ visit_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context:
visit(n.stmts, builder, ast_context);
case Expr_Stmt:
visit(n.expr, builder, ast_context);
+ case Branch_Stmt:
+ write_semantic_token(builder, n.tok, ast_context.file.src, .Type, .None);
+ case Poly_Type:
+ write_semantic_string(builder, n.dollar, "$", ast_context.file.src, .Operator, .None);
+ visit(n.type, builder, ast_context);
+ visit(n.specialization, builder, ast_context);
case Range_Stmt:
write_semantic_string(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None);
@@ -329,7 +340,8 @@ visit_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context:
write_semantic_token(builder, n.relpath, ast_context.file.src, .String, .None);
case:
- log.warnf("unhandled write node %v", n);
+ log.errorf("unhandled semantic token node %v", n);
+ //panic(fmt.tprintf("Missed semantic token handling %v", n));
}
}
@@ -337,16 +349,14 @@ visit_basic_lit :: proc(basic_lit: ast.Basic_Lit, builder: ^SemanticTokenBuilder
using analysis;
if symbol, ok := resolve_basic_lit(ast_context, basic_lit); ok {
-
- if generic, ok := symbol.value.(index.SymbolGenericValue); ok {
-
- ident := generic.expr.derived.(ast.Ident);
-
- if ident.name == "string" {
- write_semantic_node(builder, generic.expr, ast_context.file.src, .String, .None);
- } else if ident.name == "int" {
- write_semantic_node(builder, generic.expr, ast_context.file.src, .Number, .None);
- } else {
+ if untyped, ok := symbol.value.(index.SymbolUntypedValue); ok {
+ switch untyped.type {
+ case .Bool:
+ write_semantic_token(builder, basic_lit.tok, ast_context.file.src, .Keyword, .None);
+ case .Float, .Integer:
+ write_semantic_token(builder, basic_lit.tok, ast_context.file.src, .Number, .None);
+ case .String:
+ write_semantic_token(builder, basic_lit.tok, ast_context.file.src, .String, .None);
}
}
}
@@ -455,7 +465,6 @@ visit_enum_fields :: proc(node: ast.Enum_Type, builder: ^SemanticTokenBuilder, a
}
for field in node.fields {
-
if ident, ok := field.derived.(Ident); ok {
write_semantic_node(builder, field, ast_context.file.src, .EnumMember, .None);
}
@@ -476,7 +485,6 @@ visit_struct_fields :: proc(node: ast.Struct_Type, builder: ^SemanticTokenBuilde
}
for field in node.fields.list {
-
for name in field.names {
if ident, ok := name.derived.(Ident); ok {
write_semantic_node(builder, name, ast_context.file.src, .Property, .None);
@@ -488,6 +496,34 @@ visit_struct_fields :: proc(node: ast.Struct_Type, builder: ^SemanticTokenBuilde
}
visit_selector :: proc(selector: ^ast.Selector_Expr, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
- using analysis;
- using ast;
+
+ if _, ok := selector.expr.derived.(ast.Selector_Expr); ok {
+ visit_selector(cast(^ast.Selector_Expr)selector.expr, builder, ast_context);
+ } else {
+ visit(selector.expr, builder, ast_context);
+ builder.selector = true;
+ }
+
+ if symbol, ok := builder.symbols[cast(uintptr)selector]; ok {
+ if symbol.type == .Variable {
+ write_semantic_node(builder, selector.field, ast_context.file.src, .Method, .None);
+ }
+ #partial switch v in symbol.value {
+ case index.SymbolPackageValue:
+ write_semantic_node(builder, selector.field, ast_context.file.src, .Namespace, .None);
+ case index.SymbolStructValue:
+ write_semantic_node(builder, selector.field, ast_context.file.src, .Struct, .None);
+ case index.SymbolEnumValue:
+ write_semantic_node(builder, selector.field, ast_context.file.src, .Enum, .None);
+ case index.SymbolUnionValue:
+ write_semantic_node(builder, selector.field, ast_context.file.src, .Enum, .None);
+ case index.SymbolProcedureValue:
+ write_semantic_node(builder, selector.field, ast_context.file.src, .Function, .None);
+ case index.SymbolProcedureGroupValue:
+ write_semantic_node(builder, selector.field, ast_context.file.src, .Function, .None);
+ }
+ }
+
+
+ //((a.d).b).c
} \ No newline at end of file
diff --git a/src/server/signature.odin b/src/server/signature.odin
index 03d9ce7..d187336 100644
--- a/src/server/signature.odin
+++ b/src/server/signature.odin
@@ -118,7 +118,7 @@ get_signature_information :: proc(document: ^common.Document, position: common.P
signature_help: SignatureHelp;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
position_context, ok := get_document_position_context(document, position, .SignatureHelp);
diff --git a/src/server/types.odin b/src/server/types.odin
index 1dbcbe1..bf0cff4 100644
--- a/src/server/types.odin
+++ b/src/server/types.odin
@@ -298,6 +298,7 @@ OlsConfig :: struct {
enable_format: bool,
enable_procedure_context: bool,
enable_snippets: bool,
+ enable_inlay_hints: bool,
verbose: bool,
file_log: bool,
formatter: common.Format_Config,
@@ -352,6 +353,11 @@ HoverParams :: struct {
position: common.Position,
}
+
+InlayParams :: struct {
+ textDocument: TextDocumentIdentifier,
+}
+
Hover :: struct {
contents: MarkupContent,
range: common.Range,