aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2022-01-05 09:33:03 +0100
committerDaniel Gavin <danielgavin5@hotmail.com>2022-01-05 09:33:03 +0100
commit93df32b34b80da4d62644004160294d1d068a934 (patch)
treeed42f20ebda9993b1ad0ebe552043be5e9bd7bc5 /src/server
parent508b2487f45fac7a58549e4c5f8cde3f250ae568 (diff)
more refractoring by trying to store the variable information on the symbol.
Diffstat (limited to 'src/server')
-rw-r--r--src/server/completion.odin61
-rw-r--r--src/server/definition.odin3
-rw-r--r--src/server/document_symbols.odin3
-rw-r--r--src/server/documents.odin12
-rw-r--r--src/server/hover.odin2
-rw-r--r--src/server/inlay_hints.odin2
-rw-r--r--src/server/lens.odin2
-rw-r--r--src/server/requests.odin4
-rw-r--r--src/server/semantic_tokens.odin490
-rw-r--r--src/server/signature.odin2
10 files changed, 32 insertions, 549 deletions
diff --git a/src/server/completion.odin b/src/server/completion.odin
index 87490ac..0885e00 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -50,7 +50,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);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
get_globals(document.ast, &ast_context);
@@ -232,10 +232,13 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if ident, ok := position_context.selector.derived.(ast.Ident); ok {
- is_variable := resolve_ident_is_variable(ast_context, ident);
- is_package := resolve_ident_is_package(ast_context, ident);
+ symbol, ok := resolve_type_identifier(ast_context, ident);
- if (!is_variable && !is_package && selector.type != .Enum && ident.name != "") || (is_variable && selector.type == .Enum) {
+ if !ok {
+ return;
+ }
+
+ if (symbol.type != .Variable && symbol.type != .Package && selector.type != .Enum && ident.name != "") || (symbol.type == .Variable && selector.type == .Enum) {
return;
}
}
@@ -386,7 +389,6 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
list.isIncomplete = false;
for name in v.names {
-
item := CompletionItem {
label = name,
kind = .EnumMember,
@@ -439,11 +441,9 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
case index.SymbolPackageValue:
-
list.isIncomplete = true;
if searched, ok := index.fuzzy_search(field, {selector.pkg}); ok {
-
for search in searched {
symbol := search.symbol;
@@ -477,7 +477,6 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) {
-
using analysis;
items := make([dynamic]CompletionItem, context.temp_allocator);
@@ -497,17 +496,12 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
//enum switch infer
if position_context.switch_stmt != nil && position_context.case_clause != nil && position_context.switch_stmt.cond != nil {
-
used_enums := make(map[string]bool, 5, context.temp_allocator);
if block, ok := position_context.switch_stmt.body.derived.(ast.Block_Stmt); ok {
-
for stmt in block.stmts {
-
if case_clause, ok := stmt.derived.(ast.Case_Clause); ok {
-
for name in case_clause.list {
-
if implicit, ok := name.derived.(ast.Implicit_Selector_Expr); ok {
used_enums[implicit.field.name] = true;
}
@@ -517,9 +511,7 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if enum_value, ok := unwrap_enum(ast_context, position_context.switch_stmt.cond); ok {
-
for name in enum_value.names {
-
if name in used_enums {
continue;
}
@@ -658,7 +650,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if position_context.binary != nil && (position_context.binary.op.text == "==" || position_context.binary.op.text == "!=") {
-
context_node: ^ast.Expr;
enum_node: ^ast.Expr;
@@ -673,7 +664,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
if context_node != nil && enum_node != nil {
if enum_value, ok := unwrap_enum(ast_context, enum_node); ok {
for name in enum_value.names {
-
item := CompletionItem {
label = name,
kind = .EnumMember,
@@ -690,19 +680,15 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if position_context.assign != nil && position_context.assign.rhs != nil && position_context.assign.lhs != nil {
-
rhs_index: int;
for elem in position_context.assign.rhs {
if position_in_node(elem, position_context.position) {
break;
} else {
-
//procedures are the only types that can return more than one value
if symbol, ok := resolve_type_expression(ast_context, elem); ok {
-
if procedure, ok := symbol.value.(index.SymbolProcedureValue); ok {
-
if procedure.return_types == nil {
return;
}
@@ -718,7 +704,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
if len(position_context.assign.lhs) > rhs_index {
if enum_value, ok := unwrap_enum(ast_context, position_context.assign.lhs[rhs_index]); ok {
for name in enum_value.names {
-
item := CompletionItem {
label = name,
kind = .EnumMember,
@@ -735,7 +720,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if position_context.returns != nil && position_context.function != nil {
-
return_index: int;
if position_context.returns.results == nil {
@@ -743,7 +727,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
for result, i in position_context.returns.results {
-
if position_in_node(result, position_context.position) {
return_index = i;
break;
@@ -759,11 +742,8 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if len(position_context.function.type.results.list) > return_index {
-
if enum_value, ok := unwrap_enum(ast_context, position_context.function.type.results.list[return_index].type); ok {
-
for name in enum_value.names {
-
item := CompletionItem {
label = name,
kind = .EnumMember,
@@ -780,21 +760,15 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if position_context.call != nil {
-
if call, ok := position_context.call.derived.(ast.Call_Expr); ok {
-
parameter_index, parameter_ok := find_position_in_call_param(ast_context, call);
-
if symbol, ok := resolve_type_expression(ast_context, call.expr); ok && parameter_ok {
-
if proc_value, ok := symbol.value.(index.SymbolProcedureValue); ok {
-
if len(proc_value.arg_types) <= parameter_index {
return;
}
if enum_value, ok := unwrap_enum(ast_context, proc_value.arg_types[parameter_index].type); ok {
-
for name in enum_value.names {
item := CompletionItem {
label = name,
@@ -815,7 +789,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) {
-
using analysis;
items := make([dynamic]CompletionItem, context.temp_allocator);
@@ -824,7 +797,6 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
CombinedResult :: struct {
score: f32,
- variable: ^ast.Ident,
snippet: Snippet_Info,
name: string,
type: index.SymbolType,
@@ -931,7 +903,6 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
pkg = symbol.pkg,
signature = symbol.signature,
returns = symbol.returns,
- variable = ident,
});
}
}
@@ -965,7 +936,6 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
pkg = symbol.pkg,
signature = symbol.signature,
returns = symbol.returns,
- variable = ident,
});
}
}
@@ -1049,7 +1019,6 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
top_results := combined[0:(min(50, len(combined)))];
for result in top_results {
-
result := result;
//Skip procedures when the position is in proc decl
@@ -1085,16 +1054,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
documentation = result.doc,
};
- if result.variable != nil {
- if ok := resolve_ident_is_variable(ast_context, result.variable^); ok {
- item.kind = .Variable;
- result.type = .Variable;
- } else {
- item.kind = cast(CompletionItemKind)result.type;
- }
- } else {
- item.kind = cast(CompletionItemKind)result.type;
- }
+ item.kind = cast(CompletionItemKind)result.type;
if result.type == .Function {
item.insertText = fmt.tprintf("%v($0)", item.label);
@@ -1143,7 +1103,6 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte
}
if !strings.contains(position_context.import_stmt.fullpath, "/") && !strings.contains(position_context.import_stmt.fullpath, ":") {
-
for key, _ in common.config.collections {
item := CompletionItem {
@@ -1158,7 +1117,6 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte
}
for pkg in search_for_packages(absolute_path) {
-
item := CompletionItem {
detail = pkg,
label = filepath.base(pkg),
@@ -1176,7 +1134,6 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte
}
search_for_packages :: proc(fullpath: string) -> [] string {
-
packages := make([dynamic]string, context.temp_allocator);
fh, err := os.open(fullpath);
@@ -1198,7 +1155,6 @@ search_for_packages :: proc(fullpath: string) -> [] string {
}
get_type_switch_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) {
-
using analysis;
items := make([dynamic]CompletionItem, context.temp_allocator);
@@ -1253,7 +1209,6 @@ get_type_switch_completion :: proc(ast_context: ^analysis.AstContext, position_c
}
get_core_insert_package_if_non_existent :: proc(ast_context: ^analysis.AstContext, pkg: string) -> (TextEdit, bool) {
-
builder := strings.make_builder(context.temp_allocator);
for imp in ast_context.imports {
diff --git a/src/server/definition.odin b/src/server/definition.odin
index 6d44227..01641b4 100644
--- a/src/server/definition.odin
+++ b/src/server/definition.odin
@@ -20,14 +20,13 @@ import "shared:index"
import "shared:analysis"
get_definition_location :: proc(document: ^common.Document, position: common.Position) -> ([]common.Location, bool) {
-
using analysis;
locations := make([dynamic]common.Location, context.temp_allocator);
location: common.Location;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
uri: string;
diff --git a/src/server/document_symbols.odin b/src/server/document_symbols.odin
index 0b4402e..db18e56 100644
--- a/src/server/document_symbols.odin
+++ b/src/server/document_symbols.odin
@@ -21,10 +21,9 @@ 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);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
get_globals(document.ast, &ast_context);
diff --git a/src/server/documents.odin b/src/server/documents.odin
index 2dc1685..71e6cd0 100644
--- a/src/server/documents.odin
+++ b/src/server/documents.odin
@@ -105,11 +105,11 @@ document_open :: proc(uri_string: string, text: string, config: ^common.Config,
return .InvalidRequest;
}
- document.uri = uri;
+ document.uri = uri;
document.client_owned = true;
- document.text = transmute([]u8)text;
- document.used_text = len(document.text);
- document.allocator = document_get_allocator();
+ document.text = transmute([]u8)text;
+ document.used_text = len(document.text);
+ document.allocator = document_get_allocator();
if err := document_refresh(document, config, writer); err != .None {
return err;
@@ -124,6 +124,8 @@ document_open :: proc(uri_string: string, text: string, config: ^common.Config,
allocator = document_get_allocator(),
};
+ document.symbol_cache = make(map[int]rawptr, 10, common.scratch_allocator(document.allocator));
+
if err := document_refresh(&document, config, writer); err != .None {
return err;
}
@@ -248,7 +250,7 @@ document_close :: proc(uri_string: string) -> common.Error {
}
document_refresh :: proc(document: ^common.Document, config: ^common.Config, writer: ^Writer) -> common.Error {
-
+ clear(&document.symbol_cache);
errors, ok := parse_document(document, config);
if !ok {
diff --git a/src/server/hover.odin b/src/server/hover.odin
index 840e666..b77c0b1 100644
--- a/src/server/hover.odin
+++ b/src/server/hover.odin
@@ -60,7 +60,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);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
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 7d96c84..e67aac9 100644
--- a/src/server/inlay_hints.odin
+++ b/src/server/inlay_hints.odin
@@ -14,7 +14,7 @@ get_inlay_hints :: proc(document: ^common.Document) -> ([]InlayHint, bool) {
hints := make([dynamic]InlayHint, context.temp_allocator);
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
Visit_Data :: struct {
calls: [dynamic]ast.Call_Expr,
diff --git a/src/server/lens.odin b/src/server/lens.odin
index 9d80d0c..822a115 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);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
get_globals(document.ast, &ast_context);
diff --git a/src/server/requests.odin b/src/server/requests.odin
index fc5ea68..7892432 100644
--- a/src/server/requests.odin
+++ b/src/server/requests.odin
@@ -674,6 +674,8 @@ request_completion :: proc (task: ^common.Task) {
return;
}
+ //context.allocator = common.scratch_allocator(document.allocator);
+
list: CompletionList;
list, ok = get_completion_list(document, completition_params.position, completition_params.context_);
@@ -912,7 +914,6 @@ notification_did_save :: proc (task: ^common.Task) {
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);
@@ -937,7 +938,6 @@ notification_did_save :: proc (task: ^common.Task) {
}
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] = {};
diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin
index 40f9020..f7d01dd 100644
--- a/src/server/semantic_tokens.odin
+++ b/src/server/semantic_tokens.odin
@@ -40,7 +40,7 @@ SemanticTokenModifiers :: enum {
}
SemanticTokensClientCapabilities :: struct {
- requests: struct {
+ requests: struct {
range: bool,
},
tokenTypes: []string,
@@ -75,15 +75,11 @@ SemanticTokens :: struct {
}
SemanticTokenBuilder :: struct {
- current_function: ^ast.Node,
- current_start: int,
- selector_member: bool,
- selector_package: bool,
- tokens: [dynamic]u32,
+ current_start: int,
+ tokens: [dynamic]u32,
}
make_token_builder :: proc(allocator := context.temp_allocator) -> SemanticTokenBuilder {
-
return {
tokens = make([dynamic]u32, context.temp_allocator),
};
@@ -95,22 +91,20 @@ 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) -> SemanticTokens {
using analysis;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, context.temp_allocator);
- builder := make_token_builder();
-
- get_globals(document.ast, &ast_context);
+ builder := make_token_builder();
if document.ast.pkg_decl != nil {
write_semantic_token(&builder, document.ast.pkg_token, document.ast.src, .Keyword, .None);
}
+ resolve_entire_file(document, context.temp_allocator);
+
for decl in document.ast.decls {
if range.start.line <= decl.pos.line && decl.end.line <= range.end.line {
- write_semantic_tokens(decl, &builder, &ast_context);
+
}
}
@@ -118,7 +112,6 @@ 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);
@@ -129,7 +122,6 @@ write_semantic_node :: proc(builder: ^SemanticTokenBuilder, node: ^ast.Node, src
}
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);
@@ -137,8 +129,7 @@ write_semantic_token :: proc(builder: ^SemanticTokenBuilder, token: tokenizer.To
builder.current_start = token.pos.offset;
}
-write_semantic_token_pos :: proc(builder: ^SemanticTokenBuilder, pos: tokenizer.Pos, name: string, src: string, type: SemanticTokenTypes, modifier: SemanticTokenModifiers) {
-
+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);
@@ -146,466 +137,3 @@ write_semantic_token_pos :: proc(builder: ^SemanticTokenBuilder, pos: tokenizer.
builder.current_start = pos.offset;
}
-resolve_and_write_ident :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) -> (is_member: bool, is_package: bool, package_name: string) {
-
- using analysis;
-
- n := node.derived.(ast.Ident);
-
- package_name = ast_context.document_package;
- ast_context.current_package = ast_context.document_package;
- ast_context.use_globals = true;
- ast_context.use_locals = true;
-
- if resolve_ident_is_variable(ast_context, n) {
- write_semantic_node(builder, node, ast_context.file.src, .Variable, .None);
- is_member = true;
- } else if symbol, ok := resolve_type_identifier(ast_context, n); ok {
- #partial switch v in symbol.value {
- case index.SymbolPackageValue:
- write_semantic_node(builder, node, ast_context.file.src, .Namespace, .None);
- is_package = true;
- package_name = symbol.pkg;
- case index.SymbolStructValue:
- write_semantic_node(builder, node, ast_context.file.src, .Struct, .None);
- case index.SymbolEnumValue:
- write_semantic_node(builder, node, ast_context.file.src, .Enum, .None);
- case index.SymbolUnionValue:
- write_semantic_node(builder, node, ast_context.file.src, .Enum, .None);
- case index.SymbolProcedureValue:
- write_semantic_node(builder, node, ast_context.file.src, .Function, .None);
- case index.SymbolProcedureGroupValue:
- write_semantic_node(builder, node, ast_context.file.src, .Function, .None);
- case index.SymbolGenericValue:
- #partial switch symbol.type {
- case .Keyword:
- write_semantic_node(builder, node, ast_context.file.src, .Keyword, .None);
- }
- }
- }
-
- return;
-}
-
-write_semantic_tokens :: proc {
- write_semantic_tokens_node,
- write_semantic_tokens_dynamic_array,
- write_semantic_tokens_array,
- write_semantic_tokens_stmt,
-};
-
-write_semantic_tokens_array :: proc(array: $A/[]^$T, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- for elem, i in array {
- write_semantic_tokens(elem, builder, ast_context);
- }
-}
-
-write_semantic_tokens_dynamic_array :: proc(array: $A/[dynamic]^$T, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- for elem, i in array {
- write_semantic_tokens(elem, builder, ast_context);
- }
-}
-
-write_semantic_tokens_stmt :: proc(node: ^ast.Stmt, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
- ast_context.current_package = ast_context.document_package;
- ast_context.use_globals = true;
- ast_context.use_locals = true;
- builder.selector_member = false;
- write_semantic_tokens_node(node, builder, ast_context);
-}
-
-write_semantic_tokens_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- using ast;
-
- if node == nil {
- return;
- }
-
- switch n in node.derived {
- case Ellipsis:
- write_semantic_token_pos(builder, node.pos, "..", ast_context.file.src, .Operator, .None);
- write_semantic_tokens(n.expr, builder, ast_context);
- case Ident:
- get_locals_at(builder.current_function, node, ast_context);
- resolve_and_write_ident(node, builder, ast_context);
- case Selector_Expr:
- write_semantic_selector(cast(^Selector_Expr)node, builder, ast_context);
- case Pointer_Type:
- write_semantic_token_pos(builder, node.pos, "^", ast_context.file.src, .Operator, .None);
- write_semantic_tokens(n.elem, builder, ast_context);
- case Value_Decl:
- write_semantic_tokens_value_decl(n, builder, ast_context);
- case Block_Stmt:
- write_semantic_tokens(n.stmts, builder, ast_context);
- case Expr_Stmt:
- write_semantic_tokens(n.expr, builder, ast_context);
- case Range_Stmt:
- write_semantic_token_pos(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None);
-
- for val in n.vals {
- if ident, ok := val.derived.(Ident); ok {
- write_semantic_node(builder, val, ast_context.file.src, .Variable, .None);
- }
- }
-
- write_semantic_token_pos(builder, n.in_pos, "in", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.expr, builder, ast_context);
- write_semantic_tokens(n.body, builder, ast_context);
- case If_Stmt:
- write_semantic_token_pos(builder, n.if_pos, "if", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.init, builder, ast_context);
- write_semantic_tokens(n.cond, builder, ast_context);
- write_semantic_tokens(n.body, builder, ast_context);
- if n.else_stmt != nil {
- write_semantic_token_pos(builder, n.else_pos, "else", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.else_stmt, builder, ast_context);
- }
- case For_Stmt:
- write_semantic_token_pos(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.init, builder, ast_context);
- write_semantic_tokens(n.cond, builder, ast_context);
- write_semantic_tokens(n.post, builder, ast_context);
- write_semantic_tokens(n.body, builder, ast_context);
- case Switch_Stmt:
- write_semantic_token_pos(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.init, builder, ast_context);
- write_semantic_tokens(n.cond, builder, ast_context);
- write_semantic_tokens(n.body, builder, ast_context);
- case Type_Switch_Stmt:
- write_semantic_token_pos(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.tag, builder, ast_context);
- write_semantic_tokens(n.expr, builder, ast_context);
- write_semantic_tokens(n.body, builder, ast_context);
- case Assign_Stmt:
- for l in n.lhs {
- if ident, ok := l.derived.(Ident); ok {
- write_semantic_node(builder, l, ast_context.file.src, .Variable, .None);
- } else {
- write_semantic_tokens(l, builder, ast_context);
- }
- }
-
- write_semantic_token_op(builder, n.op, ast_context.file.src);
- write_semantic_tokens(n.rhs, builder, ast_context);
- case Case_Clause:
- write_semantic_token_pos(builder, n.case_pos, "case", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.list, builder, ast_context);
- write_semantic_tokens(n.body, builder, ast_context);
- case Call_Expr:
- //could there be any other type then .Function for call expr? No point of computing it if not.
- if ident, ok := n.expr.derived.(Ident); ok {
- write_semantic_node(builder, n.expr, ast_context.file.src, .Function, .None);
- } else {
- write_semantic_tokens(n.expr, builder, ast_context);
- }
- write_semantic_tokens(n.args, builder, ast_context);
- case Implicit_Selector_Expr:
- write_semantic_node(builder, n.field, ast_context.file.src, .Enum, .None);
- case Array_Type:
- write_semantic_tokens(n.elem, builder, ast_context);
- case Binary_Expr:
- write_semantic_tokens(n.left, builder, ast_context);
- write_semantic_token_op(builder, n.op, ast_context.file.src);
- write_semantic_tokens(n.right, builder, ast_context);
- case Comp_Lit:
- write_semantic_tokens(n.type, builder, ast_context);
- write_semantic_tokens(n.elems, builder, ast_context);
- case Struct_Type:
- write_semantic_token_pos(builder, n.pos, "struct", ast_context.file.src, .Keyword, .None);
- write_semantic_struct_fields(n, builder, ast_context);
- case Type_Assertion:
- write_semantic_tokens(n.expr, builder, ast_context);
- write_semantic_tokens(n.type, builder, ast_context);
- case Type_Cast:
- write_semantic_token_pos(builder, n.pos, "cast", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.type, builder, ast_context);
- write_semantic_tokens(n.expr, builder, ast_context);
- case Paren_Expr:
- write_semantic_tokens(n.expr, builder, ast_context);
- case Deref_Expr:
- write_semantic_tokens(n.expr, builder, ast_context);
- case Return_Stmt:
- write_semantic_token_pos(builder, n.pos, "return", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.results, builder, ast_context);
- case Dynamic_Array_Type:
- write_semantic_token_pos(builder, n.dynamic_pos, "dynamic", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.elem, builder, ast_context);
- case Field_Value:
- if ident, ok := n.field.derived.(Ident); ok {
- write_semantic_node(builder, n.field, ast_context.file.src, .Property, .None);
- }
-
- write_semantic_tokens(n.value, builder, ast_context);
- case Index_Expr:
- write_semantic_tokens(n.expr, builder, ast_context);
- write_semantic_tokens(n.index, builder, ast_context);
- case Basic_Lit:
- write_semantic_token_basic_lit(n, builder, ast_context);
- case Unary_Expr:
- write_semantic_tokens(n.expr, builder, ast_context);
- case Implicit:
- case Slice_Expr:
- write_semantic_tokens(n.expr, builder, ast_context);
- case Using_Stmt:
- write_semantic_token_pos(builder, n.pos, "using", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.list, builder, ast_context);
- case Map_Type:
- write_semantic_token_pos(builder, n.tok_pos, "map", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.key, builder, ast_context);
- write_semantic_tokens(n.value, builder, ast_context);
- case Defer_Stmt:
- write_semantic_token_pos(builder, n.pos, "defer", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.stmt, builder, ast_context);
- case Import_Decl:
- write_semantic_token(builder, n.import_tok, ast_context.file.src, .Keyword, .None);
-
- if n.name.text != "" {
- write_semantic_token(builder, n.name, ast_context.file.src, .Namespace, .None);
- }
-
- write_semantic_token(builder, n.relpath, ast_context.file.src, .String, .None);
- case:
- log.warnf("unhandled write node %v", n);
- }
-}
-
-write_semantic_token_basic_lit :: proc(basic_lit: ast.Basic_Lit, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- 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 {
- }
- }
- }
-}
-
-write_semantic_tokens_value_decl :: proc(value_decl: ast.Value_Decl, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- using ast;
-
- if value_decl.type != nil {
-
- for name in value_decl.names {
- write_semantic_node(builder, name, ast_context.file.src, .Variable, .None);
- }
-
- write_semantic_tokens(value_decl.type, builder, ast_context);
-
- return;
- }
-
- if len(value_decl.values) == 1 {
-
- switch v in value_decl.values[0].derived {
- case Struct_Type:
- write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Struct, .None);
- write_semantic_token_pos(builder, v.pos, "struct", ast_context.file.src, .Keyword, .None);
- write_semantic_struct_fields(v, builder, ast_context);
- case Enum_Type:
- write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Enum, .None);
- write_semantic_token_pos(builder, v.pos, "enum", ast_context.file.src, .Keyword, .None);
- write_semantic_enum_fields(v, builder, ast_context);
- case Proc_Group:
- write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Function, .None);
- write_semantic_token_pos(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None);
- for arg in v.args {
- if ident, ok := arg.derived.(Ident); ok {
- write_semantic_node(builder, arg, ast_context.file.src, .Function, .None);
- }
- }
- case Proc_Lit:
- write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Function, .None);
- write_semantic_token_pos(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None);
- write_semantic_proc_type(v.type, builder, ast_context);
-
- last_function := builder.current_function;
- builder.current_function = value_decl.values[0];
- write_semantic_tokens(v.body, builder, ast_context);
- builder.current_function = last_function;
- case:
- for name in value_decl.names {
- write_semantic_node(builder, name, ast_context.file.src, .Variable, .None);
- }
-
- write_semantic_tokens(value_decl.values[0], builder, ast_context);
- }
- } else {
-
- for name in value_decl.names {
- write_semantic_node(builder, name, ast_context.file.src, .Variable, .None);
- }
-
- for value in value_decl.values {
- write_semantic_tokens(value, builder, ast_context);
- }
- }
-}
-
-write_semantic_token_op :: proc(builder: ^SemanticTokenBuilder, token: tokenizer.Token, src: string) {
-
- if token.text == "=" {
- write_semantic_token_pos(builder, token.pos, token.text, src, .Operator, .None);
- } else if token.text == "in" {
- write_semantic_token_pos(builder, token.pos, token.text, src, .Keyword, .None);
- }
-}
-
-write_semantic_proc_type :: proc(node: ^ast.Proc_Type, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- using ast;
-
- if node == nil {
- return;
- }
-
- if node.params != nil {
-
- for param in node.params.list {
-
- for name in param.names {
-
- if ident, ok := name.derived.(Ident); ok {
- write_semantic_node(builder, name, ast_context.file.src, .Parameter, .None);
- }
- }
-
- write_semantic_tokens(param.type, builder, ast_context);
- }
- }
-
- if node.results != nil {
-
- for result in node.results.list {
-
- for name in result.names {
-
- if ident, ok := name.derived.(Ident); ok {
- //write_semantic_node(builder, name, ast_context.file.src, .Parameter, .None);
- }
- }
-
- write_semantic_tokens(result.type, builder, ast_context);
- }
- }
-}
-
-write_semantic_enum_fields :: proc(node: ast.Enum_Type, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- using ast;
-
- if node.fields == nil {
- return;
- }
-
- for field in node.fields {
-
- if ident, ok := field.derived.(Ident); ok {
- write_semantic_node(builder, field, ast_context.file.src, .EnumMember, .None);
- }
- else if f, ok := field.derived.(Field_Value); ok {
- if ident, ok := f.field.derived.(Ident); ok {
- write_semantic_node(builder, f.field, ast_context.file.src, .EnumMember, .None);
- }
- write_semantic_tokens(f.value, builder, ast_context);
- }
- }
-}
-
-write_semantic_struct_fields :: proc(node: ast.Struct_Type, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- using ast;
-
- if node.fields == nil {
- return;
- }
-
- 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);
- }
- }
-
- write_semantic_tokens(field.type, builder, ast_context);
- }
-}
-
-write_semantic_selector :: proc(selector: ^ast.Selector_Expr, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- using analysis;
- using ast;
-
- if _, ok := selector.expr.derived.(Selector_Expr); !ok {
- get_locals_at(builder.current_function, selector.expr, ast_context);
-
- if symbol, ok := resolve_type_expression(ast_context, selector.expr); ok {
-
- #partial switch v in symbol.value {
- case index.SymbolStructValue:
- builder.selector_member = true;
- }
-
- }
-
- } else {
- write_semantic_tokens(selector.expr, builder, ast_context);
- }
-
- if symbol, ok := resolve_type_expression(ast_context, selector); ok && !builder.selector_member {
-
- #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.SymbolProcedureGroupValue:
- write_semantic_node(builder, selector.field, ast_context.file.src, .Function, .None);
- case index.SymbolGenericValue:
- #partial switch symbol.type {
- case .Keyword:
- write_semantic_node(builder, selector.field, ast_context.file.src, .Keyword, .None);
- }
- }
- } else if (builder.selector_member) {
- write_semantic_node(builder, selector.field, ast_context.file.src, .Property, .None);
- }
-}
-
-get_locals_at :: proc(function: ^ast.Node, position: ^ast.Node, ast_context: ^analysis.AstContext) {
-
- using analysis;
-
- clear_locals(ast_context);
-
- if function == nil {
- return;
- }
-
- if position == nil {
- return;
- }
-
- document_position := DocumentPositionContext {
- position = position.end.offset,
- };
-
- get_locals(ast_context.file, function, ast_context, &document_position);
-}
diff --git a/src/server/signature.odin b/src/server/signature.odin
index d7fe289..91e2b47 100644
--- a/src/server/signature.odin
+++ b/src/server/signature.odin
@@ -127,7 +127,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);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
position_context, ok := get_document_position_context(document, position, .SignatureHelp);