aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2023-05-18 18:10:11 +0200
committerDanielGavin <danielgavin5@hotmail.com>2023-05-18 18:10:11 +0200
commitadfb252f6a0283a565fc5cd801baa1b8c7161d3d (patch)
tree7c4808d78c459fcd8089c555f1e7b3f32cb9b330 /src
parent2b0dccaa496fd809e36e7d979995e843bca28bfb (diff)
Add support for gotos on comp literal fields
Diffstat (limited to 'src')
-rw-r--r--src/server/analysis.odin114
-rw-r--r--src/server/definition.odin11
-rw-r--r--src/testing/testing.odin4
3 files changed, 103 insertions, 26 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 5a04a3a..5d9fbe6 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -362,20 +362,13 @@ resolve_type_comp_literal :: proc(
return {}, nil, false
}
- element_index := 0
prev_package := ast_context.current_package
ast_context.current_package = current_symbol.pkg
defer ast_context.current_package = prev_package
- for elem, i in current_comp_lit.elems {
- if position_in_node(elem, position_context.position) {
- element_index = i
- }
- }
-
- for elem in current_comp_lit.elems {
+ for elem, element_index in current_comp_lit.elems {
if !position_in_node(elem, position_context.position) {
continue
}
@@ -409,7 +402,8 @@ resolve_type_comp_literal :: proc(
}
}
} else if comp_value, ok := elem.derived.(^ast.Comp_Lit); ok { //indexed
- if s, ok := current_symbol.value.(SymbolStructValue); ok {
+ #partial switch s in current_symbol.value {
+ case SymbolStructValue:
if len(s.types) <= element_index {
return {}, {}, false
}
@@ -429,6 +423,38 @@ resolve_type_comp_literal :: proc(
comp_value,
)
}
+ case SymbolSliceValue:
+ if symbol, ok := resolve_type_expression(ast_context, s.expr);
+ ok {
+ return resolve_type_comp_literal(
+ ast_context,
+ position_context,
+ symbol,
+ comp_value,
+ )
+ }
+
+ case SymbolDynamicArrayValue:
+ if symbol, ok := resolve_type_expression(ast_context, s.expr);
+ ok {
+ return resolve_type_comp_literal(
+ ast_context,
+ position_context,
+ symbol,
+ comp_value,
+ )
+ }
+
+ case SymbolFixedArrayValue:
+ if symbol, ok := resolve_type_expression(ast_context, s.expr);
+ ok {
+ return resolve_type_comp_literal(
+ ast_context,
+ position_context,
+ symbol,
+ comp_value,
+ )
+ }
}
}
}
@@ -1957,6 +1983,28 @@ expand_struct_usings :: proc(
return {names = names[:], types = types[:], ranges = ranges[:]}
}
+resolve_comp_literal :: proc(
+ ast_context: ^AstContext,
+ position_context: ^DocumentPositionContext,
+) -> (
+ symbol: Symbol,
+ ok: bool,
+) {
+ symbol = resolve_type_expression(
+ ast_context,
+ position_context.parent_comp_lit.type,
+ ) or_return
+
+ symbol, _ = resolve_type_comp_literal(
+ ast_context,
+ position_context,
+ symbol,
+ position_context.parent_comp_lit,
+ ) or_return
+
+ return symbol, true
+}
+
resolve_implicit_selector :: proc(
ast_context: ^AstContext,
position_context: ^DocumentPositionContext,
@@ -2290,28 +2338,50 @@ resolve_location_identifier :: proc(
return {}, false
}
+resolve_location_comp_lit_field :: proc(
+ ast_context: ^AstContext,
+ position_context: ^DocumentPositionContext,
+) -> (
+ symbol: Symbol,
+ ok: bool,
+) {
+ reset_ast_context(ast_context)
+
+ ast_context.current_package = ast_context.document_package
+
+ symbol = resolve_comp_literal(ast_context, position_context) or_return
+
+ field := position_context.field_value.field.derived.(^ast.Ident) or_return
+
+ if struct_value, ok := symbol.value.(SymbolStructValue); ok {
+ for name, i in struct_value.names {
+ if name == field.name {
+ symbol.range = struct_value.ranges[i]
+ }
+
+ }
+ }
+
+ return symbol, true
+}
resolve_location_implicit_selector :: proc(
ast_context: ^AstContext,
position_context: ^DocumentPositionContext,
implicit_selector: ^ast.Implicit_Selector_Expr,
) -> (
- Symbol,
- bool,
+ symbol: Symbol,
+ ok: bool,
) {
reset_ast_context(ast_context)
ast_context.current_package = ast_context.document_package
- symbol, ok := resolve_implicit_selector(
+ symbol = resolve_implicit_selector(
ast_context,
position_context,
implicit_selector,
- )
-
- if !ok {
- return {}, false
- }
+ ) or_return
#partial switch v in symbol.value {
case SymbolEnumValue:
@@ -2329,17 +2399,13 @@ resolve_location_selector :: proc(
ast_context: ^AstContext,
selector: ^ast.Selector_Expr,
) -> (
- Symbol,
- bool,
+ symbol: Symbol,
+ ok: bool,
) {
reset_ast_context(ast_context)
ast_context.current_package = ast_context.document_package
- symbol, ok := resolve_type_expression(ast_context, selector.expr)
-
- if !ok {
- return {}, false
- }
+ symbol = resolve_type_expression(ast_context, selector.expr) or_return
field: string
diff --git a/src/server/definition.odin b/src/server/definition.odin
index 68cfac2..4c712eb 100644
--- a/src/server/definition.odin
+++ b/src/server/definition.odin
@@ -131,6 +131,17 @@ get_definition_location :: proc(
location.range = resolved.range
uri = resolved.uri
}
+ } else if position_context.field_value != nil &&
+ 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.implicit_selector_expr != nil {
if resolved, ok := resolve_location_implicit_selector(
&ast_context,
diff --git a/src/testing/testing.odin b/src/testing/testing.odin
index 0d97870..2e020e1 100644
--- a/src/testing/testing.odin
+++ b/src/testing/testing.odin
@@ -366,7 +366,7 @@ expect_definition_locations :: proc(
for expect_location, i in expect_locations {
for location, j in locations {
- if location == expect_location {
+ if location.range == expect_location.range {
flags[i] += 1
}
}
@@ -377,7 +377,7 @@ expect_definition_locations :: proc(
testing.errorf(
t,
"Expected location %v, but received %v",
- expect_locations[i],
+ expect_locations[i].range,
locations,
)
}