aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2020-12-12 00:08:13 +0100
committerDanielGavin <danielgavin5@hotmail.com>2020-12-12 00:08:13 +0100
commiteb1bf335ada34c25410fecd5dc8885e2572fb212 (patch)
treec00572c1a84666bb0c81e22c7a401f711bf7f147 /src/server
parent2400136b4e8627733980cb9baf692cfa119a4d0f (diff)
started work on hover(disabled currently through json config, unstable)
Diffstat (limited to 'src/server')
-rw-r--r--src/server/analysis.odin149
-rw-r--r--src/server/requests.odin75
-rw-r--r--src/server/types.odin28
3 files changed, 231 insertions, 21 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index e348781..f588bfd 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -29,6 +29,7 @@ DocumentPositionContextHint :: enum {
Completion,
SignatureHelp,
Definition,
+ Hover,
};
DocumentPositionContext :: struct {
@@ -1568,11 +1569,11 @@ concatenate_symbols_information :: proc(ast_context: ^AstContext, symbol: index.
if symbol.type == .Function {
if symbol.returns != "" {
- return strings.concatenate({pkg, "::", symbol.name, "::", symbol.signature, " -> ", symbol.returns}, context.temp_allocator);
+ return strings.concatenate({pkg, ".", symbol.name, ": proc", symbol.signature, " -> ", symbol.returns}, context.temp_allocator);
}
else {
- return strings.concatenate({pkg, "::", symbol.name, "::", symbol.signature}, context.temp_allocator);
+ return strings.concatenate({pkg, ".", symbol.name, ": proc", symbol.signature}, context.temp_allocator);
}
}
@@ -1616,6 +1617,37 @@ get_definition_location :: proc(document: ^Document, position: common.Position)
if position_context.selector != nil {
+ //if the base selector is the client wants to go to.
+ if base, ok := position_context.selector.derived.(ast.Ident); ok && position_context.identifier != nil {
+
+ ident := position_context.identifier.derived.(ast.Ident);
+
+ if ident.name == base.name {
+
+ if resolved, ok := resolve_location_identifier(&ast_context, ident); ok {
+ location.range = resolved.range;
+
+ if resolved.uri == "" {
+ location.uri = document.uri.uri;
+ }
+
+ else {
+ location.uri = resolved.uri;
+ }
+
+ return location, true;
+ }
+
+ else {
+ return location, false;
+ }
+
+ }
+
+ }
+
+ //otherwise it's the field the client wants to go to.
+
selector: index.Symbol;
ast_context.use_locals = true;
@@ -1695,6 +1727,117 @@ get_definition_location :: proc(document: ^Document, position: common.Position)
return location, true;
}
+write_hover_content :: proc(ast_context: ^AstContext, symbol: index.Symbol) -> MarkupContent {
+ content: MarkupContent;
+
+ cat := concatenate_symbols_information(ast_context, symbol);
+
+ if cat != "" {
+ content.kind = "markdown";
+ content.value = fmt.tprintf("```odin\n %v\n```\n%v", cat, symbol.doc);
+ }
+
+ else {
+ content.kind = "plaintext";
+ }
+
+ return content;
+}
+
+get_hover_information :: proc(document: ^Document, position: common.Position) -> (Hover, bool) {
+
+ hover: Hover;
+
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name);
+
+ position_context, ok := get_document_position_context(document, position, .Hover);
+
+ get_globals(document.ast, &ast_context);
+
+ if position_context.function != nil {
+ get_locals(document.ast, position_context.function, &ast_context, &position_context);
+ }
+
+ if position_context.selector != nil && position_context.identifier != nil {
+
+ //if the base selector is the client wants to go to.
+ if base, ok := position_context.selector.derived.(ast.Ident); ok && position_context.identifier != nil {
+
+ ident := position_context.identifier.derived.(ast.Ident);
+
+ if ident.name == base.name {
+
+ if resolved, ok := resolve_type_identifier(&ast_context, ident); ok {
+ hover.range = common.get_token_range(position_context.identifier^, document.ast.src);
+ hover.contents = write_hover_content(&ast_context, resolved);
+ return hover, true;
+ }
+
+ }
+
+ }
+
+
+ ast_context.use_locals = true;
+ ast_context.use_globals = true;
+ ast_context.current_package = ast_context.document_package;
+
+ selector: index.Symbol;
+ selector, ok = resolve_type_expression(&ast_context, position_context.selector);
+
+ if !ok {
+ return {}, true;
+ }
+
+ field: string;
+
+ if position_context.field != nil {
+
+ switch v in position_context.field.derived {
+ case ast.Ident:
+ field = v.name;
+ }
+
+ }
+
+ hover.range = common.get_token_range(position_context.identifier^, document.ast.src);
+
+ log.info(hover);
+
+ #partial switch v in selector.value {
+ case index.SymbolStructValue:
+ for name, i in v.names {
+ if strings.compare(name, field) == 0 {
+ if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok {
+ hover.contents = write_hover_content(&ast_context, symbol);
+ return hover, true;
+ }
+ }
+ }
+ case index.SymbolPackageValue:
+ if symbol, ok := index.lookup(field, selector.pkg); ok {
+ hover.contents = write_hover_content(&ast_context, symbol);
+ return hover, true;
+ }
+ }
+
+ }
+
+ else if position_context.identifier != nil {
+
+ if resolved, ok := resolve_type_identifier(&ast_context, position_context.identifier.derived.(ast.Ident)); ok {
+ log.info(position_context.identifier^);
+ hover.range = common.get_token_range(position_context.identifier^, document.ast.src);
+ log.info(hover.range);
+ hover.contents = write_hover_content(&ast_context, resolved);
+ return hover, true;
+ }
+
+ }
+
+ return {}, true;
+}
+
//ERROR can't got to common.Position
get_completion_list :: proc(document: ^Document, position: common.Position) -> (CompletionList, bool) {
@@ -2433,7 +2576,7 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP
}
}
- else if position_context.hint == .Definition && n.field != nil {
+ else if (position_context.hint == .Definition || position_context.hint == .Hover) && n.field != nil {
position_context.selector = n.expr;
position_context.field = n.field;
get_document_position(n.expr, position_context);
diff --git a/src/server/requests.odin b/src/server/requests.odin
index fdda2e8..7c0b2c1 100644
--- a/src/server/requests.odin
+++ b/src/server/requests.odin
@@ -37,6 +37,7 @@ RequestType :: enum {
DocumentSymbol,
SemanticTokensFull,
SemanticTokensRange,
+ Hover,
};
RequestInfo :: struct {
@@ -184,7 +185,8 @@ request_map : map [string] RequestType =
"textDocument/signatureHelp" = .SignatureHelp,
"textDocument/documentSymbol" = .DocumentSymbol,
"textDocument/semanticTokens/full" = .SemanticTokensFull,
- "textDocument/semanticTokens/range" = .SemanticTokensRange};
+ "textDocument/semanticTokens/range" = .SemanticTokensRange,
+ "textDocument/hover" = .Hover};
handle_error :: proc(err: common.Error, id: RequestId, writer: ^Writer) {
@@ -280,6 +282,8 @@ handle_request :: proc(request: json.Value, config: ^common.Config, writer: ^Wri
task_proc = request_semantic_token_full;
case .SemanticTokensRange:
task_proc = request_semantic_token_range;
+ case .Hover:
+ task_proc = request_hover;
}
task := common.Task {
@@ -290,7 +294,7 @@ handle_request :: proc(request: json.Value, config: ^common.Config, writer: ^Wri
#partial switch request_type {
case .Initialize, .Initialized:
task_proc(&task);
- case .Completion, .Definition:
+ case .Completion, .Definition, .Hover:
uri := root["params"].value.(json.Object)["textDocument"].value.(json.Object)["uri"].value.(json.String);
@@ -393,6 +397,9 @@ request_initialize :: proc(task: ^common.Task) {
thread_count := 2;
+ enable_document_symbols: bool;
+ enable_hover: bool;
+
if len(config.workspace_folders) > 0 {
//right now just look at the first workspace - TODO(daniel, add multiple workspace support)
@@ -409,6 +416,9 @@ request_initialize :: proc(task: ^common.Task) {
if unmarshal(value, ols_config, context.temp_allocator) == .None {
thread_count = ols_config.thread_pool_count;
+ enable_document_symbols = ols_config.enable_document_symbols;
+ enable_hover = ols_config.enable_hover;
+ //config.enable_semantic_tokens = ols_config.enable_semantic_tokens;
for p in ols_config.collections {
config.collections[strings.clone(p.name)] = strings.clone(strings.to_lower(p.path, context.temp_allocator));
@@ -429,14 +439,14 @@ request_initialize :: proc(task: ^common.Task) {
//ERROR can't go to defintion
for format in initialize_params.capabilities.textDocument.hover.contentFormat {
- if format == .Markdown {
+ if format == "markdown" {
config.hover_support_md = true;
}
}
for format in initialize_params.capabilities.textDocument.completion.documentationFormat {
- if format == .Markdown {
+ if format == "markdown" {
config.completion_support_md = true;
}
}
@@ -477,14 +487,15 @@ request_initialize :: proc(task: ^common.Task) {
triggerCharacters = signatureTriggerCharacters,
},
semanticTokensProvider = SemanticTokensOptions {
- range = true,
- full = true,
+ range = config.enable_semantic_tokens,
+ full = config.enable_semantic_tokens,
legend = SemanticTokensLegend {
tokenTypes = token_types,
tokenModifiers = token_modifiers,
},
},
- documentSymbolProvider = true,
+ documentSymbolProvider = enable_document_symbols,
+ hoverProvider = enable_hover,
},
},
id = id,
@@ -794,7 +805,10 @@ request_semantic_token_full :: proc(task: ^common.Task) {
};
symbols: SemanticTokens;
- //symbols := get_semantic_tokens(document, range);
+
+ if config.enable_semantic_tokens {
+ symbols = get_semantic_tokens(document, range);
+ }
response := make_response_message(
params = symbols,
@@ -829,7 +843,10 @@ request_semantic_token_range :: proc(task: ^common.Task) {
}
symbols: SemanticTokens;
- //symbols := get_semantic_tokens(document, semantic_params.range);
+
+ if config.enable_semantic_tokens {
+ symbols = get_semantic_tokens(document, semantic_params.range);
+ }
response := make_response_message(
params = symbols,
@@ -871,4 +888,44 @@ request_document_symbols :: proc(task: ^common.Task) {
);
send_response(response, writer);
+}
+
+request_hover :: proc(task: ^common.Task) {
+
+ info := get_request_info(task);
+
+ using info;
+
+ defer document_release(document);
+ defer json.destroy_value(root);
+ defer free(info);
+
+ params_object, ok := params.value.(json.Object);
+
+ if !ok {
+ handle_error(.ParseError, id, writer);
+ return;
+ }
+
+ hover_params: HoverParams;
+
+ if unmarshal(params, hover_params, context.temp_allocator) != .None {
+ handle_error(.ParseError, id, writer);
+ return;
+ }
+
+ hover: Hover;
+ hover, ok = get_hover_information(document, hover_params.position);
+
+ if !ok {
+ handle_error(.InternalError, id, writer);
+ return;
+ }
+
+ response := make_response_message(
+ params = hover,
+ id = id,
+ );
+
+ send_response(response, writer);
} \ No newline at end of file
diff --git a/src/server/types.odin b/src/server/types.odin
index 820ae3a..87d1370 100644
--- a/src/server/types.odin
+++ b/src/server/types.odin
@@ -23,6 +23,7 @@ ResponseParams :: union {
SignatureHelp,
[] DocumentSymbol,
SemanticTokens,
+ Hover,
};
ResponseMessage :: struct {
@@ -38,7 +39,7 @@ ResponseMessageError :: struct {
};
ResponseError :: struct {
- code: common.Error,
+ code: common.Error,
message: string,
};
@@ -73,13 +74,8 @@ RequestInitializeParams :: struct {
capabilities: ClientCapabilities,
};
-MarkupKind :: enum {
- Plaintext,
- Markdown,
-};
-
MarkupContent :: struct {
- kind: MarkupKind,
+ kind: string,
value: string,
};
@@ -90,6 +86,7 @@ ServerCapabilities :: struct {
signatureHelpProvider: SignatureHelpOptions,
semanticTokensProvider: SemanticTokensOptions,
documentSymbolProvider: bool,
+ hoverProvider: bool,
};
CompletionOptions :: struct {
@@ -99,7 +96,7 @@ CompletionOptions :: struct {
HoverClientCapabilities :: struct {
dynamicRegistration: bool,
- contentFormat: [dynamic] MarkupKind,
+ contentFormat: [dynamic] string,
};
DocumentSymbolClientCapabilities :: struct {
@@ -119,7 +116,7 @@ TextDocumentClientCapabilities :: struct {
};
CompletionClientCapabilities :: struct {
- documentationFormat: [dynamic] MarkupKind,
+ documentationFormat: [dynamic] string,
};
ParameterInformationCapabilities :: struct {
@@ -282,6 +279,9 @@ ParameterInformation :: struct {
OlsConfig :: struct {
collections: [dynamic] OlsConfigCollection,
thread_pool_count: int,
+ enable_semantic_tokens: bool,
+ enable_document_symbols: bool,
+ enable_hover: bool,
};
OlsConfigCollection :: struct {
@@ -325,3 +325,13 @@ DocumentSymbol :: struct {
selectionRange: common.Range,
children: [] DocumentSymbol,
};
+
+HoverParams :: struct {
+ textDocument: TextDocumentIdentifier,
+ position: common.Position,
+};
+
+Hover :: struct {
+ contents: MarkupContent,
+ range: common.Range,
+}; \ No newline at end of file