diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2025-07-16 00:39:54 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-16 00:39:54 +0200 |
| commit | 38089237530bad6b009df5d73d787bd077b38b93 (patch) | |
| tree | c0c3d4ad8b90651e710fa6e1ba8caffff6f9fc7c /src/server | |
| parent | 5dcf2252629655d45ea4e3169f003b4010665fd6 (diff) | |
| parent | c44d3222d470f5a83637260cd8f9a06fd52d7f03 (diff) | |
Merge pull request #751 from BradLewis/feat/resolve-named-parameters
Resolve named procedure params
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/analysis.odin | 97 | ||||
| -rw-r--r-- | src/server/completion.odin | 2 | ||||
| -rw-r--r-- | src/server/definition.odin | 20 | ||||
| -rw-r--r-- | src/server/documentation.odin | 8 | ||||
| -rw-r--r-- | src/server/file_resolve.odin | 8 | ||||
| -rw-r--r-- | src/server/hover.odin | 50 | ||||
| -rw-r--r-- | src/server/references.odin | 15 | ||||
| -rw-r--r-- | src/server/symbol.odin | 50 | ||||
| -rw-r--r-- | src/server/type_definition.odin | 66 |
9 files changed, 225 insertions, 91 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 0c3178a..2bd6717 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -649,31 +649,6 @@ get_unnamed_arg_count :: proc(args: []^ast.Expr) -> int { return total } -get_procedure_arg_count :: proc(v: SymbolProcedureValue) -> int { - total := 0 - for proc_arg in v.arg_types { - for name in proc_arg.names { - total += 1 - } - } - return total -} - -// Gets the call argument type at the specified index -get_proc_call_argument_type :: proc(value: SymbolProcedureValue, parameter_index: int) -> (^ast.Field, bool) { - index := 0 - for arg in value.arg_types { - for name in arg.names { - if index == parameter_index { - return arg, true - } - index += 1 - } - } - - return nil, false -} - /* Figure out which function the call expression is using out of the list from proc group */ @@ -712,7 +687,7 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou named := false if !resolve_all_possibilities { - arg_count := get_procedure_arg_count(procedure) + arg_count := get_proc_arg_count(procedure) if call_expr != nil && arg_count < call_unnamed_arg_count { break next_fn } @@ -2238,6 +2213,76 @@ resolve_location_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) - return {}, false } +resolve_location_proc_param_name :: proc( + ast_context: ^AstContext, + position_context: ^DocumentPositionContext, +) -> ( + symbol: Symbol, + ok: bool, +) { + ident := position_context.field_value.field.derived.(^ast.Ident) or_return + call := position_context.call.derived.(^ast.Call_Expr) or_return + symbol = resolve_type_expression(ast_context, call) or_return + + reset_ast_context(ast_context) + if value, ok := symbol.value.(SymbolProcedureValue); ok { + if arg_name, ok := get_proc_arg_name_from_name(value, ident.name); ok { + symbol.range = common.get_token_range(arg_name, ast_context.file.src) + } + } + return symbol, true +} + +resolve_type_location_proc_param_name :: proc( + ast_context: ^AstContext, + position_context: ^DocumentPositionContext, +) -> ( + call_symbol: Symbol, + ok: bool, +) { + ident := position_context.field_value.field.derived.(^ast.Ident) or_return + call := position_context.call.derived.(^ast.Call_Expr) or_return + call_symbol = resolve_type_expression(ast_context, call) or_return + + reset_ast_context(ast_context) + if value, ok := call_symbol.value.(SymbolProcedureValue); ok { + if symbol, ok := resolve_type_expression(ast_context, position_context.field_value.value); ok { + symbol.type_pkg = symbol.pkg + symbol.type_name = symbol.name + symbol.pkg = call_symbol.name + symbol.name = ident.name + return symbol, true + } + } + return call_symbol, false +} + +// resolves the underlying location of type of the named param +resolve_location_proc_param_name_type :: proc( + ast_context: ^AstContext, + position_context: ^DocumentPositionContext, +) -> ( + call_symbol: Symbol, + ok: bool, +) { + ident := position_context.field_value.field.derived.(^ast.Ident) or_return + call := position_context.call.derived.(^ast.Call_Expr) or_return + call_symbol = resolve_type_expression(ast_context, call) or_return + + reset_ast_context(ast_context) + if value, ok := call_symbol.value.(SymbolProcedureValue); ok { + if arg_type, ok := get_proc_arg_type_from_name(value, ident.name); ok { + if symbol, ok := resolve_location_type_expression(ast_context, arg_type.type); ok { + return symbol, true + } + } + if symbol, ok := resolve_location_type_expression(ast_context, position_context.field_value.value); ok { + return symbol, true + } + } + return call_symbol, false +} + resolve_location_comp_lit_field :: proc( ast_context: ^AstContext, position_context: ^DocumentPositionContext, diff --git a/src/server/completion.odin b/src/server/completion.odin index 1381967..59f6a6c 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -1171,7 +1171,7 @@ get_implicit_completion :: proc( } if proc_value, ok := symbol.value.(SymbolProcedureValue); ok { - arg_type, arg_type_ok := get_proc_call_argument_type(proc_value, parameter_index) + arg_type, arg_type_ok := get_proc_arg_type_from_index(proc_value, parameter_index) if !arg_type_ok { return } diff --git a/src/server/definition.odin b/src/server/definition.odin index ffd6cc0..c793f32 100644 --- a/src/server/definition.odin +++ b/src/server/definition.odin @@ -106,14 +106,22 @@ get_definition_location :: proc(document: ^Document, position: common.Position) return {}, false } } else if position_context.field_value != nil && - position_context.comp_lit != nil && !is_expr_basic_lit(position_context.field_value.field) && position_in_node(position_context.field_value.field, position_context.position) { - if resolved, ok := resolve_location_comp_lit_field(&ast_context, &position_context); ok { - location.range = resolved.range - uri = resolved.uri - } else { - return {}, false + if position_context.comp_lit != nil { + if resolved, ok := resolve_location_comp_lit_field(&ast_context, &position_context); ok { + location.range = resolved.range + uri = resolved.uri + } else { + return {}, false + } + } else if position_context.call != nil { + if resolved, ok := resolve_location_proc_param_name(&ast_context, &position_context); ok { + location.range = resolved.range + uri = resolved.uri + } else { + return {}, false + } } } else if position_context.implicit_selector_expr != nil { if resolved, ok := resolve_location_implicit_selector( diff --git a/src/server/documentation.odin b/src/server/documentation.odin index 86dfe81..417815a 100644 --- a/src/server/documentation.odin +++ b/src/server/documentation.odin @@ -149,16 +149,16 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string { return strings.to_string(sb) case SymbolStructValue: sb := strings.builder_make(ast_context.allocator) - if is_variable { - append_variable_full_name(&sb, ast_context, symbol, pointer_prefix) - strings.write_string(&sb, " :: ") - } else if symbol.type_name != "" { + if symbol.type_name != "" { if symbol.type_pkg == "" { fmt.sbprintf(&sb, "%s%s :: ", pointer_prefix, symbol.type_name) } else { pkg_name := get_pkg_name(ast_context, symbol.type_pkg) fmt.sbprintf(&sb, "%s%s.%s :: ", pointer_prefix, pkg_name, symbol.type_name) } + } else if is_variable { + append_variable_full_name(&sb, ast_context, symbol, pointer_prefix) + strings.write_string(&sb, " :: ") } if len(v.names) == 0 { strings.write_string(&sb, "struct {}") diff --git a/src/server/file_resolve.odin b/src/server/file_resolve.odin index 70a4b99..e930f9d 100644 --- a/src/server/file_resolve.odin +++ b/src/server/file_resolve.odin @@ -229,6 +229,14 @@ resolve_node :: proc(node: ^ast.Node, data: ^FileResolveData) { } resolve_node(n.value, data) + } else if data.flag != .None && data.position_context.call != nil { + if symbol, ok := resolve_location_proc_param_name(data.ast_context, data.position_context); ok { + data.symbols[cast(uintptr)node] = SymbolAndNode { + node = n.field, + symbol = symbol, + } + } + resolve_node(n.value, data) } else { resolve_node(n.field, data) resolve_node(n.value, data) diff --git a/src/server/hover.odin b/src/server/hover.odin index 9d8519c..f23bc23 100644 --- a/src/server/hover.odin +++ b/src/server/hover.odin @@ -201,10 +201,8 @@ get_hover_information :: proc(document: ^Document, position: common.Position) -> symbol.type_pkg = symbol.pkg symbol.pkg = bit_field_symbol.name symbol.name = identifier.name - if value, ok := bit_field_symbol.value.(SymbolBitFieldValue); ok { - symbol.comment = get_comment(value.comments[i]) - symbol.doc = get_doc(value.docs[i], context.temp_allocator) - } + symbol.comment = get_comment(value.comments[i]) + symbol.doc = get_doc(value.docs[i], context.temp_allocator) symbol.signature = get_bit_field_field_signature(value, i) hover.contents = write_hover_content(&ast_context, symbol) return hover, true, true @@ -217,11 +215,25 @@ get_hover_information :: proc(document: ^Document, position: common.Position) -> } } - if position_context.field_value != nil && position_context.comp_lit != nil { - if comp_symbol, ok := resolve_comp_literal(&ast_context, &position_context); ok { - if field, ok := position_context.field_value.field.derived.(^ast.Ident); ok { - if position_in_node(field, position_context.position) { - if v, ok := comp_symbol.value.(SymbolStructValue); ok { + if position_context.field_value != nil && position_in_node(position_context.field_value.field, position_context.position) { + if position_context.comp_lit != nil { + if comp_symbol, ok := resolve_comp_literal(&ast_context, &position_context); ok { + if field, ok := position_context.field_value.field.derived.(^ast.Ident); ok { + if position_in_node(field, position_context.position) { + if v, ok := comp_symbol.value.(SymbolStructValue); ok { + for name, i in v.names { + if name == field.name { + if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok { + symbol.name = name + symbol.pkg = comp_symbol.name + symbol.signature = node_to_string(v.types[i]) + hover.contents = write_hover_content(&ast_context, symbol) + return hover, true, true + } + } + } + } + } else if v, ok := comp_symbol.value.(SymbolBitFieldValue); ok { for name, i in v.names { if name == field.name { if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok { @@ -234,21 +246,17 @@ get_hover_information :: proc(document: ^Document, position: common.Position) -> } } } - } else if v, ok := comp_symbol.value.(SymbolBitFieldValue); ok { - for name, i in v.names { - if name == field.name { - if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok { - symbol.name = name - symbol.pkg = comp_symbol.name - symbol.signature = node_to_string(v.types[i]) - hover.contents = write_hover_content(&ast_context, symbol) - return hover, true, true - } - } - } } } } + + if position_context.call != nil { + if symbol, ok := resolve_type_location_proc_param_name(&ast_context, &position_context); ok { + symbol.signature = get_signature(&ast_context, symbol) + hover.contents = write_hover_content(&ast_context, symbol) + return hover, true, true + } + } } if position_context.selector != nil && diff --git a/src/server/references.odin b/src/server/references.odin index 7e791b8..230243a 100644 --- a/src/server/references.odin +++ b/src/server/references.odin @@ -145,13 +145,18 @@ prepare_references :: proc( } } else if position_context.field_value != nil && - position_context.comp_lit != nil && !is_expr_basic_lit(position_context.field_value.field) && position_in_node(position_context.field_value.field, position_context.position) { - symbol, ok = resolve_location_comp_lit_field(ast_context, position_context) - - if !ok { - return + if position_context.comp_lit != nil { + symbol, ok = resolve_location_comp_lit_field(ast_context, position_context) + if !ok { + return + } + } else if position_context.call != nil { + symbol, ok = resolve_location_proc_param_name(ast_context, position_context) + if !ok { + return + } } resolve_flag = .Field diff --git a/src/server/symbol.odin b/src/server/symbol.odin index 08a6788..b65349c 100644 --- a/src/server/symbol.odin +++ b/src/server/symbol.odin @@ -525,6 +525,56 @@ expand_objc :: proc(ast_context: ^AstContext, b: ^SymbolStructValueBuilder) { } } +get_proc_arg_count :: proc(v: SymbolProcedureValue) -> int { + total := 0 + for proc_arg in v.arg_types { + for name in proc_arg.names { + total += 1 + } + } + return total +} + +// Gets the call argument type at the specified index +get_proc_arg_type_from_index :: proc(value: SymbolProcedureValue, parameter_index: int) -> (^ast.Field, bool) { + index := 0 + for arg in value.arg_types { + for name in arg.names { + if index == parameter_index { + return arg, true + } + index += 1 + } + } + return nil, false +} + +get_proc_arg_type_from_name :: proc(v: SymbolProcedureValue, name: string) -> (^ast.Field, bool) { + for arg in v.arg_types { + for arg_name in arg.names { + if ident, ok := arg_name.derived.(^ast.Ident); ok { + if name == ident.name { + return arg, true + } + } + } + } + return nil, false +} + +get_proc_arg_name_from_name :: proc(v: SymbolProcedureValue, name: string) -> (^ast.Ident, bool) { + for arg in v.arg_types { + for arg_name in arg.names { + if ident, ok := arg_name.derived.(^ast.Ident); ok { + if name == ident.name { + return ident, true + } + } + } + } + return nil, false +} + new_clone_symbol :: proc(data: Symbol, allocator := context.allocator) -> ^Symbol { new_symbol := new(Symbol, allocator) new_symbol^ = data diff --git a/src/server/type_definition.odin b/src/server/type_definition.odin index 900c060..94fb211 100644 --- a/src/server/type_definition.odin +++ b/src/server/type_definition.odin @@ -66,6 +66,44 @@ get_type_definition_locations :: proc(document: ^Document, position: common.Posi } } + if position_context.field_value != nil && position_in_node(position_context.field_value.field, position_context.position) { + if position_context.comp_lit != nil { + if comp_symbol, ok := resolve_comp_literal(&ast_context, &position_context); ok { + if field, ok := position_context.field_value.field.derived.(^ast.Ident); ok { + if position_in_node(field, position_context.position) { + if v, ok := comp_symbol.value.(SymbolStructValue); ok { + for name, i in v.names { + if name == field.name { + if symbol, ok := resolve_location_type_expression(&ast_context, v.types[i]); ok { + append_symbol_to_locations(&locations, document, symbol) + return locations[:], true + } + } + } + } + } else if v, ok := comp_symbol.value.(SymbolBitFieldValue); ok { + for name, i in v.names { + if name == field.name { + if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok { + append_symbol_to_locations(&locations, document, symbol) + return locations[:], true + } + } + } + } + } + } + } + + if position_context.call != nil { + if symbol, ok := resolve_location_proc_param_name_type(&ast_context, &position_context); ok { + append_symbol_to_locations(&locations, document, symbol) + return locations[:], true + } + } + } + + if position_context.call != nil { if call, ok := position_context.call.derived.(^ast.Call_Expr); ok { if !position_in_exprs(call.args, position_context.position) { @@ -97,34 +135,6 @@ get_type_definition_locations :: proc(document: ^Document, position: common.Posi } } - if position_context.field_value != nil && position_context.comp_lit != nil { - if comp_symbol, ok := resolve_comp_literal(&ast_context, &position_context); ok { - if field, ok := position_context.field_value.field.derived.(^ast.Ident); ok { - if position_in_node(field, position_context.position) { - if v, ok := comp_symbol.value.(SymbolStructValue); ok { - for name, i in v.names { - if name == field.name { - if symbol, ok := resolve_location_type_expression(&ast_context, v.types[i]); ok { - append_symbol_to_locations(&locations, document, symbol) - return locations[:], true - } - } - } - } - } else if v, ok := comp_symbol.value.(SymbolBitFieldValue); ok { - for name, i in v.names { - if name == field.name { - if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok { - append_symbol_to_locations(&locations, document, symbol) - return locations[:], true - } - } - } - } - } - } - } - if position_context.selector != nil && position_context.identifier != nil && position_context.field == position_context.identifier { |