diff options
| author | Daniel Gavin <danielgavin5@hotmail.com> | 2022-01-05 09:33:03 +0100 |
|---|---|---|
| committer | Daniel Gavin <danielgavin5@hotmail.com> | 2022-01-05 09:33:03 +0100 |
| commit | 93df32b34b80da4d62644004160294d1d068a934 (patch) | |
| tree | ed42f20ebda9993b1ad0ebe552043be5e9bd7bc5 /src/server | |
| parent | 508b2487f45fac7a58549e4c5f8cde3f250ae568 (diff) | |
more refractoring by trying to store the variable information on the symbol.
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/completion.odin | 61 | ||||
| -rw-r--r-- | src/server/definition.odin | 3 | ||||
| -rw-r--r-- | src/server/document_symbols.odin | 3 | ||||
| -rw-r--r-- | src/server/documents.odin | 12 | ||||
| -rw-r--r-- | src/server/hover.odin | 2 | ||||
| -rw-r--r-- | src/server/inlay_hints.odin | 2 | ||||
| -rw-r--r-- | src/server/lens.odin | 2 | ||||
| -rw-r--r-- | src/server/requests.odin | 4 | ||||
| -rw-r--r-- | src/server/semantic_tokens.odin | 490 | ||||
| -rw-r--r-- | src/server/signature.odin | 2 |
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); |