diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2024-05-09 22:38:34 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-09 22:38:34 +0200 |
| commit | f06cf17a90e8f181e8717588e1398efb06b802cc (patch) | |
| tree | e0b789e10e72d41a9aa0a2b25bc30316e340c8bd | |
| parent | 3a2b74f601cb1baeab192218daa7c79f33150396 (diff) | |
| parent | 2056c372996d75b35298c4d4fa0ee9f55858255d (diff) | |
Merge pull request #385 from thetarnav/value-decl-locals
Fix variable names in value declarations not having symbols
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | src/server/analysis.odin | 61 | ||||
| -rw-r--r-- | tests/definition_test.odin | 58 |
3 files changed, 85 insertions, 35 deletions
@@ -13,5 +13,6 @@ *node_modules /ols /odinfmt +tests/tests ols.json .vscode/settings.json diff --git a/src/server/analysis.odin b/src/server/analysis.odin index b52890b..2f6f20e 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -1219,31 +1219,22 @@ clear_local_group :: proc(ast_context: ^AstContext, id: int) { } get_local :: proc( - ast_context: ^AstContext, - offset: int, - name: string, + ast_context: AstContext, + ident: ast.Ident, ) -> ( DocumentLocal, bool, ) { - for _, locals in &ast_context.locals { - if local_stack, ok := locals[name]; ok { - for i := len(local_stack) - 1; i >= 0; i -= 1 { - if local_stack[i].offset <= offset || - local_stack[i].local_global { - if i < 0 { - return {}, false - } else { - ret := local_stack[i].rhs - if ident, ok := ret.derived.(^ast.Ident); - ok && ident.name == name { - if i - 1 < 0 { - return {}, false - } - } - return local_stack[i], true - } - } + for _, locals in ast_context.locals { + local_stack := locals[ident.name] or_continue + + #reverse for local in local_stack { + if local.offset <= ident.pos.offset || + local.local_global || + local.lhs.pos.offset == ident.pos.offset { + // checking equal offsets is a hack to allow matching lhs ident in var decls + // because otherwise minimal offset begins after the decl + return local, true } } } @@ -1313,23 +1304,23 @@ internal_resolve_type_identifier :: proc( return {}, false case "true", "false": return { - type = .Keyword, - signature = node.name, - pkg = ast_context.current_package, - value = SymbolUntypedValue{type = .Bool}, + type = .Keyword, + signature = node.name, + pkg = ast_context.current_package, + value = SymbolUntypedValue{type = .Bool}, }, true case: return { - type = .Keyword, - signature = node.name, - name = ident.name, - pkg = ast_context.current_package, - value = SymbolBasicValue{ident = ident}, + type = .Keyword, + signature = node.name, + name = ident.name, + pkg = ast_context.current_package, + value = SymbolBasicValue{ident = ident}, }, true } } - if local, ok := get_local(ast_context, node.pos.offset, node.name); + if local, ok := get_local(ast_context^, node); ok && ast_context.use_locals { is_distinct := false @@ -1858,9 +1849,9 @@ resolve_implicit_selector :: proc( proc_value.arg_types[parameter_index].type, ) } else if enum_value, ok := symbol.value.(SymbolEnumValue); - ok { - return symbol, true - } + ok { + return symbol, true + } } } } @@ -2170,7 +2161,7 @@ resolve_location_identifier :: proc( ) { symbol: Symbol - if local, ok := get_local(ast_context, node.pos.offset, node.name); ok { + if local, ok := get_local(ast_context^, node); ok { symbol.range = common.get_token_range(local.lhs, ast_context.file.src) uri := common.create_uri(local.lhs.pos.file, ast_context.allocator) symbol.pkg = ast_context.document_package diff --git a/tests/definition_test.odin b/tests/definition_test.odin index d98d92f..98b055c 100644 --- a/tests/definition_test.odin +++ b/tests/definition_test.odin @@ -172,3 +172,61 @@ ast_goto_bit_field_field_in_proc :: proc(t: ^testing.T) { test.expect_definition_locations(t, &source, {location}) } + +@(test) +ast_goto_shadowed_value_decls :: proc(t: ^testing.T) { + source0 := test.Source { + main = `package test + main :: proc() { + foo := 1 + + { + fo{*}o := 2 + } + } + `, + packages = {}, + } + test.expect_definition_locations( + t, + &source0, + {{range = {{line = 5, character = 5}, {line = 5, character = 8}}}}, + ) + + source1 := test.Source { + main = `package test + main :: proc() { + foo := 1 + + { + foo := 2 + fo{*}o + } + } + `, + packages = {}, + } + test.expect_definition_locations( + t, + &source1, + {{range = {{line = 5, character = 5}, {line = 5, character = 8}}}}, + ) + + source3 := test.Source { + main = `package test + main :: proc() { + foo := 1 + + { + foo := fo{*}o + } + } + `, + packages = {}, + } + test.expect_definition_locations( + t, + &source3, + {{range = {{line = 2, character = 4}, {line = 2, character = 7}}}}, + ) +} |