From cceb115d109c6fc86d8f6aa9cbe19517437e1519 Mon Sep 17 00:00:00 2001 From: Brad Lewis <22850972+BradLewis@users.noreply.github.com> Date: Mon, 22 Sep 2025 21:09:41 -0400 Subject: Correct resolving basic type aliases of keywords by using the underlying ident name rather than the symbol name --- src/server/analysis.odin | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/server/analysis.odin') diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 1e570b4..25f85c5 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -340,19 +340,22 @@ are_symbol_basic_same_keywords :: proc(a, b: Symbol) -> bool { if are_keyword_aliases(a.name, b.name) { return true } - if a.name != b.name { + a_value, a_ok := a.value.(SymbolBasicValue) + if !a_ok { return false } - if _, ok := a.value.(SymbolBasicValue); !ok { + + b_value, b_ok := b.value.(SymbolBasicValue) + if !b_ok { return false } - if _, ok := b.value.(SymbolBasicValue); !ok { + if a_value.ident.name != b_value.ident.name { return false } - if _, ok := keyword_map[a.name]; !ok { + if _, ok := keyword_map[a_value.ident.name]; !ok { return false } - if _, ok := keyword_map[b.name]; !ok { + if _, ok := keyword_map[b_value.ident.name]; !ok { return false } -- cgit v1.2.3 From 767c312cb90235c3160e5179adc12b47c06eb5a0 Mon Sep 17 00:00:00 2001 From: Brad Lewis <22850972+BradLewis@users.noreply.github.com> Date: Mon, 22 Sep 2025 22:01:27 -0400 Subject: Handle resolving proc overloads with nil passed as a call parameter --- src/server/analysis.odin | 43 +++++++++++++++++++++++++++++++++++++++---- tests/hover_test.odin | 21 +++++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) (limited to 'src/server/analysis.odin') diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 25f85c5..8e1d7f0 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -362,6 +362,21 @@ are_symbol_basic_same_keywords :: proc(a, b: Symbol) -> bool { return true } +is_valid_nil_symbol :: proc(symbol: Symbol) -> bool { + if symbol.pointers > 0 { + return true + } + + #partial switch v in symbol.value { + case SymbolMapValue, SymbolSliceValue, SymbolProcedureValue, SymbolDynamicArrayValue: + return true + case SymbolUnionValue: + return v.kind != .no_nil + } + + return false +} + is_symbol_same_typed :: proc(ast_context: ^AstContext, a, b: Symbol, flags: ast.Field_Flags = {}) -> bool { // In order to correctly equate the symbols for overloaded functions, we need to check both directions if same, ok := are_symbol_untyped_basic_same_typed(a, b); ok { @@ -721,6 +736,7 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou call_symbol: Symbol arg_symbol: Symbol ok: bool + is_call_arg_nil: bool if _, ok = call_arg.derived.(^ast.Bad_Expr); ok { continue @@ -729,9 +745,14 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou //named parameter if field, is_field := call_arg.derived.(^ast.Field_Value); is_field { named = true - call_symbol, ok = resolve_call_arg_type_expression(ast_context, field.value) - if !ok { - break next_fn + if ident, is_ident := field.field.derived.(^ast.Ident); is_ident && ident.name == "nil" { + is_call_arg_nil = true + ok = true + } else { + call_symbol, ok = resolve_call_arg_type_expression(ast_context, field.value) + if !ok { + break next_fn + } } if ident, is_ident := field.field.derived.(^ast.Ident); is_ident { @@ -747,7 +768,12 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou log.error("Expected name parameter after starting named parmeter phase") return {}, false } - call_symbol, ok = resolve_call_arg_type_expression(ast_context, call_arg) + if ident, is_ident := call_arg.derived.(^ast.Ident); is_ident && ident.name == "nil" { + is_call_arg_nil = true + ok = true + } else { + call_symbol, ok = resolve_call_arg_type_expression(ast_context, call_arg) + } } if !ok { @@ -786,6 +812,15 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou break next_fn } + if is_call_arg_nil { + if is_valid_nil_symbol(arg_symbol) { + continue + } else { + break next_fn + } + + } + if !is_symbol_same_typed(ast_context, call_symbol, arg_symbol, proc_arg.flags) { found := false // Are we a union variant diff --git a/tests/hover_test.odin b/tests/hover_test.odin index 9d65d8c..b2af26a 100644 --- a/tests/hover_test.odin +++ b/tests/hover_test.odin @@ -5028,6 +5028,27 @@ ast_hover_proc_overload_basic_type_alias :: proc(t: ^testing.T) { } test.expect_hover(t, &source, "test.foo :: proc(i: int)") } + +@(test) +ast_hover_proc_overload_nil_pointer :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + import "my_package" + + foo_int :: proc(i: int) {} + foo_ptr :: proc(s: ^string) {} + foo :: proc { + foo_int, + foo_ptr, + } + + main :: proc() { + f{*}oo(nil) + } + `, + } + test.expect_hover(t, &source, "test.foo :: proc(s: ^string)") +} /* Waiting for odin fix -- cgit v1.2.3 From d13384a1e9a0758e4c608f4dfe3226e78fa4803e Mon Sep 17 00:00:00 2001 From: Brad Lewis <22850972+BradLewis@users.noreply.github.com> Date: Tue, 23 Sep 2025 21:12:46 -0400 Subject: Goto definition on package use goes to package declaration --- src/server/analysis.odin | 23 +++++++++++++++++++++- src/server/documents.odin | 28 ++++++++++++++++++++++++++- tests/definition_test.odin | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) (limited to 'src/server/analysis.odin') diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 8e1d7f0..9ee621a 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -2591,7 +2591,9 @@ resolve_location_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) - symbol.uri = uri.uri symbol.flags |= {.Local} return symbol, true - } else if global, ok := ast_context.globals[node.name]; ok { + } + + if global, ok := ast_context.globals[node.name]; ok { symbol.range = common.get_token_range(global.name_expr, ast_context.file.src) uri := common.create_uri(global.expr.pos.file, ast_context.allocator) symbol.pkg = ast_context.document_package @@ -2599,6 +2601,25 @@ resolve_location_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) - return symbol, true } + for imp in ast_context.imports { + if imp.name == ast_context.current_package { + continue + } + + if strings.compare(imp.base, node.name) == 0 { + symbol := Symbol { + type = .Package, + pkg = imp.name, + value = SymbolPackageValue{}, + range = imp.range, + } + + try_build_package(symbol.pkg) + + return symbol, true + } + } + pkg := get_package_from_node(node) if symbol, ok := lookup(node.name, pkg, node.pos.file); ok { return symbol, ok diff --git a/src/server/documents.odin b/src/server/documents.odin index dee90d5..b513da6 100644 --- a/src/server/documents.odin +++ b/src/server/documents.odin @@ -29,6 +29,7 @@ Package :: struct { base: string, base_original: string, original: string, + range: common.Range, } Document :: struct { @@ -75,7 +76,7 @@ document_get_allocator :: proc() -> ^virtual.Arena { return pop(&document_storage.free_allocators) } else { allocator := new(virtual.Arena) - _ = virtual.arena_init_growing(allocator) + _ = virtual.arena_init_growing(allocator) return allocator } } @@ -427,6 +428,8 @@ parse_imports :: proc(document: ^Document, config: ^common.Config) { if i := strings.index(imp.fullpath, "\""); i == -1 { continue } + // TODO: Breakdown this range like with semantic tokens + range := get_import_range(imp, string(document.text)) //collection specified if i := strings.index(imp.fullpath, ":"); i != -1 && i > 1 && i < len(imp.fullpath) - 1 { @@ -446,6 +449,7 @@ parse_imports :: proc(document: ^Document, config: ^common.Config) { import_: Package import_.original = imp.fullpath import_.name = strings.clone(path.join(elems = {dir, p}, allocator = context.temp_allocator)) + import_.range = range if imp.name.text != "" { import_.base = imp.name.text @@ -468,6 +472,7 @@ parse_imports :: proc(document: ^Document, config: ^common.Config) { allocator = context.temp_allocator, ) import_.name = path.clean(import_.name) + import_.range = range if imp.name.text != "" { import_.base = imp.name.text @@ -488,3 +493,24 @@ parse_imports :: proc(document: ^Document, config: ^common.Config) { document.imports = imports[:] } + +get_import_range :: proc(imp: ^ast.Import_Decl, src: string) -> common.Range { + if imp.name.text != "" { + start := common.token_pos_to_position(imp.name.pos, src) + end := start + end.character += len(imp.name.text) + return { + start = start, + end = end, + } + } + + start := common.token_pos_to_position(imp.relpath.pos, src) + end := start + text_len := len(imp.relpath.text) + end.character += text_len + return { + start = start, + end = end, + } +} diff --git a/tests/definition_test.odin b/tests/definition_test.odin index 6e7c7a4..4810361 100644 --- a/tests/definition_test.odin +++ b/tests/definition_test.odin @@ -675,3 +675,51 @@ ast_goto_nested_using_struct_field :: proc(t: ^testing.T) { test.expect_definition_locations(t, &source, locations[:]) } + +@(test) +ast_goto_package_declaration :: proc(t: ^testing.T) { + packages := make([dynamic]test.Package, context.temp_allocator) + + append(&packages, test.Package{pkg = "my_package", source = `package my_package + Bar :: struct{} + `}) + source := test.Source { + main = `package test + import "my_package" + + main :: proc() { + bar: m{*}y_package.Bar + } + `, + packages = packages[:], + } + locations := []common.Location { + {range = {start = {line = 1, character = 9}, end = {line = 1, character = 21}}}, + } + + test.expect_definition_locations(t, &source, locations[:]) +} + +@(test) +ast_goto_package_declaration_with_alias :: proc(t: ^testing.T) { + packages := make([dynamic]test.Package, context.temp_allocator) + + append(&packages, test.Package{pkg = "my_package", source = `package my_package + Bar :: struct{} + `}) + source := test.Source { + main = `package test + import mp "my_package" + + main :: proc() { + bar: m{*}p.Bar + } + `, + packages = packages[:], + } + locations := []common.Location { + {range = {start = {line = 1, character = 9}, end = {line = 1, character = 11}}}, + } + + test.expect_definition_locations(t, &source, locations[:]) +} -- cgit v1.2.3 From 8a014d117e86178e5b9ab5c91fd5c92d2ebf9422 Mon Sep 17 00:00:00 2001 From: Brad Lewis <22850972+BradLewis@users.noreply.github.com> Date: Thu, 25 Sep 2025 08:13:19 -0400 Subject: Correctly infer types when indexing matrices --- src/server/analysis.odin | 7 +++++++ tests/hover_test.odin | 28 +++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'src/server/analysis.odin') diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 9ee621a..2278e00 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -1297,6 +1297,13 @@ resolve_index_expr :: proc(ast_context: ^AstContext, v: ^ast.Index_Expr) -> (Sym return indexed, true } return {}, false + case SymbolMatrixValue: + value := SymbolFixedArrayValue{ + expr = v2.expr, + len = v2.x, + } + indexed.value = value + return indexed, true } diff --git a/tests/hover_test.odin b/tests/hover_test.odin index 345e9f9..d0b844e 100644 --- a/tests/hover_test.odin +++ b/tests/hover_test.odin @@ -5033,7 +5033,6 @@ ast_hover_proc_overload_basic_type_alias :: proc(t: ^testing.T) { ast_hover_proc_overload_nil_pointer :: proc(t: ^testing.T) { source := test.Source { main = `package test - import "my_package" foo_int :: proc(i: int) {} foo_ptr :: proc(s: ^string) {} @@ -5086,6 +5085,33 @@ ast_hover_package_proc_naming_conflicting_with_another_package :: proc(t: ^testi test.expect_hover(t, &source, "my_package.foo :: proc()") } + +@(test) +ast_hover_matrix_index :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + main :: proc() { + foo: matrix[3, 2]f32 + a{*} := foo[0] + } + `, + } + test.expect_hover(t, &source, "test.a: [3]f32") +} + +@(test) +ast_hover_matrix_index_twice :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + main :: proc() { + foo: matrix[2, 3]f32 + a := foo[0] + b{*} := a[0] + } + `, + } + test.expect_hover(t, &source, "test.b: f32") +} /* Waiting for odin fix -- cgit v1.2.3