aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/analysis.odin43
-rw-r--r--src/server/collector.odin21
-rw-r--r--src/server/documentation.odin28
-rw-r--r--src/server/symbol.odin29
-rw-r--r--tests/hover_test.odin62
5 files changed, 156 insertions, 27 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 1b50468..d5ba9d1 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -1031,7 +1031,8 @@ internal_resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex
return ok
case ^Proc_Type:
out^, ok =
- make_symbol_procedure_from_ast(ast_context, node, v^, ast_context.field_name.name, {}, true, .None), true
+ make_symbol_procedure_from_ast(ast_context, node, v^, ast_context.field_name.name, {}, true, .None, nil),
+ true
return ok
case ^Bit_Field_Type:
out^, ok = make_symbol_bit_field_from_ast(ast_context, v, ast_context.field_name.name, true), true
@@ -1662,12 +1663,31 @@ resolve_local_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, loca
if !ok && !ast_context.overloading {
return_symbol, ok =
- make_symbol_procedure_from_ast(ast_context, local.rhs, v.type^, node.name, {}, false, v.inlining),
+ make_symbol_procedure_from_ast(
+ ast_context,
+ local.rhs,
+ v.type^,
+ node.name,
+ {},
+ false,
+ v.inlining,
+ v.where_clauses,
+ ),
true
}
} else {
return_symbol, ok =
- make_symbol_procedure_from_ast(ast_context, local.rhs, v.type^, node.name, {}, false, v.inlining), true
+ make_symbol_procedure_from_ast(
+ ast_context,
+ local.rhs,
+ v.type^,
+ node.name,
+ {},
+ false,
+ v.inlining,
+ v.where_clauses,
+ ),
+ true
}
case ^ast.Proc_Group:
return_symbol, ok = resolve_function_overload(ast_context, v^)
@@ -1776,6 +1796,7 @@ resolve_global_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, glo
global.attributes,
false,
v.inlining,
+ v.where_clauses,
),
true
}
@@ -1789,6 +1810,7 @@ resolve_global_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, glo
global.attributes,
false,
v.inlining,
+ v.where_clauses,
),
true
}
@@ -3026,6 +3048,7 @@ make_symbol_procedure_from_ast :: proc(
attributes: []^ast.Attribute,
type: bool,
inlining: ast.Proc_Inlining,
+ where_clauses: []^ast.Expr,
) -> Symbol {
pkg := ""
if n != nil {
@@ -3071,6 +3094,7 @@ make_symbol_procedure_from_ast :: proc(
tags = v.tags,
attributes = attributes,
inlining = inlining,
+ where_clauses = where_clauses,
}
if _, ok := get_attribute_objc_name(attributes); ok {
@@ -3252,12 +3276,13 @@ make_symbol_union_from_ast :: proc(
docs, comments := get_field_docs_and_comments(ast_context.file, v.variants, ast_context.allocator)
symbol.value = SymbolUnionValue {
- types = types[:],
- poly = v.poly_params,
- docs = docs[:],
- comments = comments[:],
- kind = v.kind,
- align = v.align,
+ types = types[:],
+ poly = v.poly_params,
+ docs = docs[:],
+ comments = comments[:],
+ kind = v.kind,
+ align = v.align,
+ where_clauses = v.where_clauses,
}
if v.poly_params != nil {
diff --git a/src/server/collector.odin b/src/server/collector.odin
index a702546..ff1c791 100644
--- a/src/server/collector.odin
+++ b/src/server/collector.odin
@@ -85,6 +85,7 @@ collect_procedure_fields :: proc(
package_map: map[string]string,
attributes: []^ast.Attribute,
inlining: ast.Proc_Inlining,
+ where_clauses: []^ast.Expr,
) -> SymbolProcedureValue {
returns := make([dynamic]^ast.Field, 0, collection.allocator)
args := make([dynamic]^ast.Field, 0, collection.allocator)
@@ -111,7 +112,6 @@ collect_procedure_fields :: proc(
append(&attrs, cloned)
}
-
value := SymbolProcedureValue {
return_types = returns[:],
orig_return_types = returns[:],
@@ -127,6 +127,7 @@ collect_procedure_fields :: proc(
tags = proc_type.tags,
attributes = attrs[:],
inlining = inlining,
+ where_clauses = clone_array(where_clauses, collection.allocator, &collection.unique_strings),
}
return value
@@ -180,6 +181,9 @@ collect_struct_fields :: proc(
}
b.poly = cast(^ast.Field_List)clone_type(struct_type.poly_params, collection.allocator, &collection.unique_strings)
+ for clause in struct_type.where_clauses {
+ append(&b.where_clauses, clone_expr(clause, collection.allocator, &collection.unique_strings))
+ }
value := to_symbol_struct_value(b)
return value
@@ -279,12 +283,13 @@ collect_union_fields :: proc(
comments := clone_dynamic_array(temp_comments, collection.allocator, &collection.unique_strings)
value := SymbolUnionValue {
- types = types[:],
- poly = cast(^ast.Field_List)clone_type(union_type.poly_params, collection.allocator, &collection.unique_strings),
- comments = comments[:],
- docs = docs[:],
- kind = union_type.kind,
- align = clone_type(union_type.align, collection.allocator, &collection.unique_strings),
+ types = types[:],
+ poly = cast(^ast.Field_List)clone_type(union_type.poly_params, collection.allocator, &collection.unique_strings),
+ comments = comments[:],
+ docs = docs[:],
+ kind = union_type.kind,
+ align = clone_type(union_type.align, collection.allocator, &collection.unique_strings),
+ where_clauses = clone_array(union_type.where_clauses, collection.allocator, &collection.unique_strings),
}
return value
@@ -568,6 +573,7 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri
package_map,
expr.attributes,
v.inlining,
+ v.where_clauses,
)
}
@@ -588,6 +594,7 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri
package_map,
expr.attributes,
.None,
+ nil,
)
case ^ast.Proc_Group:
token = v^
diff --git a/src/server/documentation.odin b/src/server/documentation.odin
index 285119d..6f591a4 100644
--- a/src/server/documentation.odin
+++ b/src/server/documentation.odin
@@ -216,6 +216,7 @@ write_signature :: proc(sb: ^strings.Builder, ast_context: ^AstContext, symbol:
strings.write_string(sb, " #align")
build_string_node(v.align, sb, false)
}
+ write_where_clauses(sb, v.where_clauses)
if len(v.types) == 0 {
strings.write_string(sb, " {}")
return
@@ -485,7 +486,14 @@ write_proc_param_list_and_return :: proc(sb: ^strings.Builder, value: SymbolProc
if len(value.orig_return_types) != 0 {
strings.write_string(sb, " -> ")
+ add_parens := false
if len(value.orig_return_types) > 1 {
+ add_parens = true
+ } else if field, ok := value.orig_return_types[0].derived.(^ast.Field); ok && len(field.names) > 0{
+ add_parens = true
+ }
+
+ if add_parens {
strings.write_string(sb, "(")
}
@@ -496,7 +504,7 @@ write_proc_param_list_and_return :: proc(sb: ^strings.Builder, value: SymbolProc
}
}
- if len(value.orig_return_types) > 1 {
+ if add_parens {
strings.write_string(sb, ")")
}
} else if value.diverging {
@@ -530,6 +538,7 @@ write_procedure_symbol_signature :: proc(sb: ^strings.Builder, value: SymbolProc
}
}
write_proc_param_list_and_return(sb, value)
+ write_where_clauses(sb, value.where_clauses)
if detailed_signature {
for tag in value.tags {
s := ""
@@ -549,6 +558,18 @@ write_procedure_symbol_signature :: proc(sb: ^strings.Builder, value: SymbolProc
}
}
+write_where_clauses :: proc(sb: ^strings.Builder, where_clauses: []^ast.Expr) {
+ if len(where_clauses) > 0 {
+ strings.write_string(sb, " where ")
+ for clause, i in where_clauses {
+ build_string_node(clause, sb, false)
+ if i != len(where_clauses) - 1 {
+ strings.write_string(sb, ", ")
+ }
+ }
+ }
+}
+
write_struct_hover :: proc(sb: ^strings.Builder, ast_context: ^AstContext, v: SymbolStructValue, depth: int) {
strings.write_string(sb, "struct")
write_poly_list(sb, v.poly, v.poly_names)
@@ -578,6 +599,9 @@ write_struct_hover :: proc(sb: ^strings.Builder, ast_context: ^AstContext, v: Sy
strings.write_string(sb, " #no_copy")
}
}
+
+ write_where_clauses(sb, v.where_clauses)
+
if len(v.names) == 0 {
strings.write_string(sb, " {}")
return
@@ -718,7 +742,7 @@ write_node :: proc(
symbol = make_symbol_bit_field_from_ast(ast_context, n, name, true)
ok = true
case ^ast.Proc_Type:
- symbol = make_symbol_procedure_from_ast(ast_context, nil, n^, name, {}, true, .None)
+ symbol = make_symbol_procedure_from_ast(ast_context, nil, n^, name, {}, true, .None, nil)
ok = true
}
if ok {
diff --git a/src/server/symbol.odin b/src/server/symbol.odin
index 9e220c5..3d176f1 100644
--- a/src/server/symbol.odin
+++ b/src/server/symbol.odin
@@ -39,6 +39,7 @@ SymbolStructValue :: struct {
args: []^ast.Expr, //The arguments in the call expression for poly
docs: []^ast.Comment_Group,
comments: []^ast.Comment_Group,
+ where_clauses: []^ast.Expr,
// Extra fields for embedded bit fields via usings
backing_types: map[int]^ast.Expr, // the base type for the bit field
@@ -74,6 +75,7 @@ SymbolProcedureValue :: struct {
tags: ast.Proc_Tags,
attributes: []^ast.Attribute,
inlining: ast.Proc_Inlining,
+ where_clauses: []^ast.Expr,
}
SymbolProcedureGroupValue :: struct {
@@ -96,13 +98,14 @@ SymbolEnumValue :: struct {
}
SymbolUnionValue :: struct {
- types: []^ast.Expr,
- poly: ^ast.Field_List,
- poly_names: []string,
- docs: []^ast.Comment_Group,
- comments: []^ast.Comment_Group,
- kind: ast.Union_Type_Kind,
- align: ^ast.Expr,
+ types: []^ast.Expr,
+ poly: ^ast.Field_List,
+ poly_names: []string,
+ docs: []^ast.Comment_Group,
+ comments: []^ast.Comment_Group,
+ kind: ast.Union_Type_Kind,
+ align: ^ast.Expr,
+ where_clauses: []^ast.Expr,
}
SymbolDynamicArrayValue :: struct {
@@ -161,9 +164,9 @@ SymbolPolyTypeValue :: struct {
Generic symbol that is used by the indexer for any variable type(constants, defined global variables, etc),
*/
SymbolGenericValue :: struct {
- expr: ^ast.Expr,
+ expr: ^ast.Expr,
field_names: []string,
- ranges: []common.Range,
+ ranges: []common.Range,
}
SymbolValue :: union {
@@ -252,6 +255,7 @@ SymbolStructValueBuilder :: struct {
unexpanded_usings: [dynamic]int,
poly: ^ast.Field_List,
poly_names: [dynamic]string,
+ where_clauses: [dynamic]^ast.Expr,
// Extra fields for embedded bit fields via usings
backing_types: map[int]^ast.Expr,
@@ -280,6 +284,7 @@ symbol_struct_value_builder_make_none :: proc(allocator := context.allocator) ->
poly_names = make([dynamic]string, allocator),
backing_types = make(map[int]^ast.Expr, allocator),
bit_sizes = make(map[int]^ast.Expr, allocator),
+ where_clauses = make([dynamic]^ast.Expr, allocator),
}
}
@@ -301,6 +306,7 @@ symbol_struct_value_builder_make_symbol :: proc(
poly_names = make([dynamic]string, allocator),
backing_types = make(map[int]^ast.Expr, allocator),
bit_sizes = make(map[int]^ast.Expr, allocator),
+ where_clauses = make([dynamic]^ast.Expr, allocator),
}
}
@@ -327,6 +333,7 @@ symbol_struct_value_builder_make_symbol_symbol_struct_value :: proc(
align = v.align,
max_field_align = v.max_field_align,
min_field_align = v.min_field_align,
+ where_clauses = slice.to_dynamic(v.where_clauses, allocator),
}
}
@@ -361,6 +368,7 @@ to_symbol_struct_value :: proc(b: SymbolStructValueBuilder) -> SymbolStructValue
max_field_align = b.max_field_align,
min_field_align = b.min_field_align,
tags = b.tags,
+ where_clauses = b.where_clauses[:],
}
}
@@ -424,6 +432,9 @@ write_struct_type :: proc(
if v.is_raw_union {
b.tags |= {.Is_Raw_Union}
}
+ for clause in v.where_clauses {
+ append(&b.where_clauses, clause)
+ }
}
expand_objc(ast_context, b)
diff --git a/tests/hover_test.odin b/tests/hover_test.odin
index 11ea8b3..5370804 100644
--- a/tests/hover_test.odin
+++ b/tests/hover_test.odin
@@ -4483,6 +4483,68 @@ ast_hover_float_binary_expr :: proc(t: ^testing.T) {
}
test.expect_hover(t, &source, "test.bar: float")
}
+
+@(test)
+ast_hover_parapoly_struct_with_where_clause :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ type_is_integer :: proc($T: typeid) -> bool {
+ return true
+ }
+
+ F{*}oo :: struct($T: typeid, $N: int) #packed
+ where type_is_integer(T),
+ N > 2 {
+ x: [N]T,
+ y: [N-2]T,
+ }
+ `,
+ }
+ test.expect_hover(t, &source, "test.Foo: struct($T: typeid, $N: int) #packed where type_is_integer(T), N > 2 {\n\tx: [N]T,\n\ty: [N - 2]T,\n}")
+}
+
+@(test)
+ast_hover_parapoly_proc_with_where_clause :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ fo{*}o :: proc(x: [$N]int) -> bool
+ where N > 2 #optional_ok {
+ fmt.println(#procedure, "was called with the parameter", x)
+ return true
+ }
+ `,
+ }
+ test.expect_hover(t, &source, "test.foo: proc(x: [$N]int) -> bool where N > 2 #optional_ok")
+}
+
+@(test)
+ast_hover_parapoly_union_with_where_clause :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ type_is_integer :: proc($T: typeid) -> bool {
+ return true
+ }
+
+ Fo{*}o :: union($T: typeid) #no_nil where type_is_integer(T){
+ T,
+ string,
+ }
+ `,
+ }
+ test.expect_hover(t, &source, "test.Foo: union($T: typeid) #no_nil where type_is_integer(T) {\n\tT,\n\tstring,\n}")
+}
+
+@(test)
+ast_hover_proc_named_return_parens :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ f{*}oo :: proc() -> (a: int) {
+ return
+ }
+ `,
+ }
+ test.expect_hover(t, &source, "test.foo: proc() -> (a: int)")
+}
/*
Waiting for odin fix