diff options
| author | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-09-23 21:12:46 -0400 |
|---|---|---|
| committer | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-09-24 15:43:58 -0400 |
| commit | d13384a1e9a0758e4c608f4dfe3226e78fa4803e (patch) | |
| tree | 30e42a80052a954f351780c16129195363d4fa22 | |
| parent | 495012ffe93385f399d3947952466448c692f0d4 (diff) | |
Goto definition on package use goes to package declaration
| -rw-r--r-- | src/server/analysis.odin | 23 | ||||
| -rw-r--r-- | src/server/documents.odin | 28 | ||||
| -rw-r--r-- | tests/definition_test.odin | 48 |
3 files changed, 97 insertions, 2 deletions
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[:]) +} |