aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamian Tarnawski <gthetarnav@gmail.com>2024-05-09 15:16:45 +0200
committerDamian Tarnawski <gthetarnav@gmail.com>2024-05-09 15:16:45 +0200
commit5167c028c2825441df1080f250ee1e5510b85965 (patch)
tree28827591d4608c3e5fd10c4352e1a3c21b02bfd6
parent3a2b74f601cb1baeab192218daa7c79f33150396 (diff)
Fix variable names in value declarations not having symbols
-rw-r--r--.gitignore1
-rw-r--r--src/server/analysis.odin61
-rw-r--r--tests/definition_test.odin36
3 files changed, 63 insertions, 35 deletions
diff --git a/.gitignore b/.gitignore
index 139a2c0..7fad674 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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..41bdbc4 100644
--- a/tests/definition_test.odin
+++ b/tests/definition_test.odin
@@ -172,3 +172,39 @@ 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 = {},
+ }
+ source1 := test.Source {
+ main = `package test
+ main :: proc() {
+ foo := 1
+
+ {
+ foo := 2
+ fo{*}o
+ }
+ }
+ `,
+ packages = {},
+ }
+
+ location := common.Location {
+ range = {{line = 5, character = 5}, {line = 5, character = 8}},
+ }
+
+ test.expect_definition_locations(t, &source0, {location})
+ test.expect_definition_locations(t, &source1, {location})
+}