aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2024-04-16 00:02:57 +0200
committerGitHub <noreply@github.com>2024-04-16 00:02:57 +0200
commit4c4b525a9730bcb2c932b8be678d7eaef96e3ff1 (patch)
tree8e4cbc91fdd7999c0aacd8c9ee6d0945d67d6b5f /src
parent63758dad45f4d0b6881c81727528ecc7d39ec5c7 (diff)
parent25de95df4262c318de7ded5bdc5ca027ab6d4872 (diff)
Merge pull request #351 from laytan/bit-field-support
support bit_fields
Diffstat (limited to 'src')
-rw-r--r--src/common/ast.odin38
-rw-r--r--src/odin/printer/visit.odin128
-rw-r--r--src/server/analysis.odin217
-rw-r--r--src/server/clone.odin7
-rw-r--r--src/server/collector.odin52
-rw-r--r--src/server/completion.odin79
-rw-r--r--src/server/document_symbols.odin2
-rw-r--r--src/server/hover.odin38
-rw-r--r--src/server/semantic_tokens.odin39
-rw-r--r--src/server/symbol.odin16
10 files changed, 609 insertions, 7 deletions
diff --git a/src/common/ast.odin b/src/common/ast.odin
index 1036b04..dbe236a 100644
--- a/src/common/ast.odin
+++ b/src/common/ast.odin
@@ -705,6 +705,13 @@ free_ast_node :: proc(node: ^ast.Node, allocator: mem.Allocator) {
case ^Relative_Type:
free_ast(n.tag, allocator)
free_ast(n.type, allocator)
+ case ^Bit_Field_Type:
+ free_ast(n.backing_type, allocator)
+ for field in n.fields do free_ast(field, allocator)
+ case ^Bit_Field_Field:
+ free_ast(n.name, allocator)
+ free_ast(n.type, allocator)
+ free_ast(n.bit_size, allocator)
case:
panic(fmt.aprintf("free Unhandled node kind: %v", node.derived))
}
@@ -913,6 +920,22 @@ node_equal_node :: proc(a, b: ^ast.Node) -> bool {
ret &= node_equal(n.args, m.args)
return ret
}
+ case ^Bit_Field_Type:
+ if n, ok := a.derived.(^Bit_Field_Type); ok {
+ if len(n.fields) != len(m.fields) do return false
+ ret := node_equal(n.backing_type, m.backing_type)
+ for i in 0..<len(n.fields) {
+ ret &= node_equal(n.fields[i], m.fields[i])
+ }
+ return ret
+ }
+ case ^Bit_Field_Field:
+ if n, ok := a.derived.(^Bit_Field_Field); ok {
+ ret := node_equal(n.name, m.name)
+ ret &= node_equal(n.type, m.type)
+ ret &= node_equal(n.bit_size, m.bit_size)
+ return ret
+ }
case ^Typeid_Type:
return true
case:
@@ -1148,6 +1171,21 @@ build_string_node :: proc(
case ^ast.Multi_Pointer_Type:
strings.write_string(builder, "[^]")
build_string(n.elem, builder, remove_pointers)
+ case ^ast.Bit_Field_Type:
+ strings.write_string(builder, "bit_field")
+ build_string(n.backing_type, builder, remove_pointers)
+ for field, i in n.fields {
+ build_string(field, builder, remove_pointers)
+ if len(n.fields) - 1 != i {
+ strings.write_string(builder, ",")
+ }
+ }
+ case ^ast.Bit_Field_Field:
+ build_string(n.name, builder, remove_pointers)
+ strings.write_string(builder, ": ")
+ build_string(n.type, builder, remove_pointers)
+ strings.write_string(builder, " | ")
+ build_string(n.bit_size, builder, remove_pointers)
}
}
diff --git a/src/odin/printer/visit.odin b/src/odin/printer/visit.odin
index 1dac999..f1d67e0 100644
--- a/src/odin/printer/visit.odin
+++ b/src/odin/printer/visit.odin
@@ -716,6 +716,94 @@ visit_enum_exprs :: proc(
}
@(private)
+visit_bit_field_fields :: proc(
+ p: ^Printer,
+ bit_field_type: ast.Bit_Field_Type,
+ options := List_Options{},
+) -> ^Document {
+ if len(bit_field_type.fields) == 0 {
+ return empty()
+ }
+
+ document := empty()
+
+ name_alignment, type_alignment := get_possible_bit_field_alignment(bit_field_type.fields)
+
+ for field, i in bit_field_type.fields {
+ if i == 0 && .Enforce_Newline in options {
+ comment, _ := visit_comments(p, bit_field_type.fields[i].pos)
+ if _, is_nil := comment.(Document_Nil); !is_nil {
+ comment = cons(comment, newline(1))
+ }
+ document = cons(comment, document)
+ }
+
+ if (.Enforce_Newline in options) {
+ document = cons(
+ document,
+ cons_with_nopl(
+ cons(
+ visit_expr(p, field.name),
+ text_position(p, ":", field.name.end),
+ ),
+ cons_with_nopl(
+ cons(
+ repeat_space(
+ name_alignment - get_node_length(field.name),
+ ),
+ visit_expr(p, field.type),
+ ),
+ cons_with_nopl(
+ cons(
+ repeat_space(
+ type_alignment - get_node_length(field.type),
+ ),
+ text_position(p, "|", field.type.end),
+ ),
+ visit_expr(p, field.bit_size),
+ ),
+ ),
+ ),
+ )
+ } else {
+ document = group(
+ cons_with_opl(
+ document,
+ cons_with_nopl(
+ cons(
+ visit_expr(p, field.name),
+ text_position(p, ":", field.name.end),
+ ),
+ cons_with_nopl(
+ cons_with_nopl(
+ visit_expr(p, field.type),
+ text_position(p, "|", field.type.end),
+ ),
+ visit_expr(p, field.bit_size),
+ ),
+ ),
+ ),
+ )
+ }
+
+ if (i != len(bit_field_type.fields) - 1 || .Trailing in options) &&
+ .Add_Comma in options {
+ document = cons(document, text(","))
+ }
+
+ if (i != len(bit_field_type.fields) - 1 && .Enforce_Newline in options) {
+ comment, _ := visit_comments(p, bit_field_type.fields[i + 1].pos)
+ document = cons(document, comment, newline(1))
+ } else if .Enforce_Newline in options {
+ comment, _ := visit_comments(p, bit_field_type.end)
+ document = cons(document, comment)
+ }
+ }
+
+ return document
+}
+
+@(private)
visit_union_exprs :: proc(
p: ^Printer,
union_type: ast.Union_Type,
@@ -1851,6 +1939,36 @@ visit_expr :: proc(
}
set_source_position(p, v.end)
+ case ^Bit_Field_Type:
+ document = text_position(p, "bit_field", v.pos)
+
+ document = cons_with_nopl(document, visit_expr(p, v.backing_type))
+
+ if len(v.fields) == 0 {
+ document = cons_with_nopl(document, text("{"))
+ document = cons(document, text("}"))
+ } else {
+ document = cons(document, break_with_space(), visit_begin_brace(p, v.pos, .Generic))
+ set_source_position(p, v.fields[0].pos)
+ document = cons(
+ document,
+ nest(
+ cons(
+ newline_position(p, 1, v.open),
+ visit_bit_field_fields(
+ p,
+ v^,
+ {.Add_Comma, .Trailing, .Enforce_Newline},
+ ),
+ ),
+ ),
+ )
+ set_source_position(p, v.end)
+
+ document = cons(document, newline(1), text_position(p, "}", v.end))
+ }
+
+ set_source_position(p, v.end)
case ^Proc_Lit:
switch v.inlining {
case .None:
@@ -2845,3 +2963,13 @@ get_possible_enum_alignment :: proc(exprs: []^ast.Expr) -> int {
return longest_name
}
+
+@(private)
+get_possible_bit_field_alignment :: proc(fields: []^ast.Bit_Field_Field) -> (longest_name: int, longest_type: int) {
+ for field in fields {
+ longest_name = max(longest_name, get_node_length(field.name))
+ longest_type = max(longest_type, get_node_length(field.type))
+ }
+
+ return
+}
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 932cc1b..100695c 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -46,6 +46,7 @@ DocumentPositionContext :: struct {
bitset_type: ^ast.Bit_Set_Type,
enum_type: ^ast.Enum_Type,
field_value: ^ast.Field_Value,
+ bit_field_type: ^ast.Bit_Field_Type,
implicit: bool, //used for completion
arrow: bool,
binary: ^ast.Binary_Expr, //used for completion
@@ -189,6 +190,30 @@ resolve_type_comp_literal :: proc(
}
}
}
+ } else if s, ok := current_symbol.value.(SymbolBitFieldValue); ok {
+ for name, i in s.names {
+ if name ==
+ field_value.field.derived.(^ast.Ident).name {
+ if symbol, ok := resolve_type_expression(
+ ast_context,
+ s.types[i],
+ ); ok {
+ //Stop at bitset, because we don't want to enter a comp_lit of a bitset
+ if _, ok := symbol.value.(SymbolBitSetValue);
+ ok {
+ return current_symbol,
+ current_comp_lit,
+ true
+ }
+ return resolve_type_comp_literal(
+ ast_context,
+ position_context,
+ symbol,
+ cast(^ast.Comp_Lit)field_value.value,
+ )
+ }
+ }
+ }
}
}
} else if comp_value, ok := elem.derived.(^ast.Comp_Lit); ok { //indexed
@@ -213,6 +238,26 @@ resolve_type_comp_literal :: proc(
comp_value,
)
}
+ case SymbolBitFieldValue:
+ if len(s.types) <= element_index {
+ return {}, {}, false
+ }
+
+ if symbol, ok := resolve_type_expression(
+ ast_context,
+ s.types[element_index],
+ ); ok {
+ //Stop at bitset, because we don't want to enter a comp_lit of a bitset
+ if _, ok := symbol.value.(SymbolBitSetValue); ok {
+ return current_symbol, current_comp_lit, true
+ }
+ return resolve_type_comp_literal(
+ ast_context,
+ position_context,
+ symbol,
+ comp_value,
+ )
+ }
case SymbolSliceValue:
if symbol, ok := resolve_type_expression(ast_context, s.expr);
ok {
@@ -825,6 +870,14 @@ internal_resolve_type_expression :: proc(
true,
),
true
+ case ^Bit_Field_Type:
+ return make_symbol_bit_field_from_ast(
+ ast_context,
+ v^,
+ ast_context.field_name,
+ true,
+ ),
+ true
case ^Basic_Directive:
return resolve_basic_directive(ast_context, v^)
case ^Binary_Expr:
@@ -1068,6 +1121,18 @@ internal_resolve_type_expression :: proc(
return symbol, ok
}
}
+ case SymbolBitFieldValue:
+ for name, i in s.names {
+ if v.field != nil && name == v.field.name {
+ ast_context.field_name = v.field^
+ symbol, ok := internal_resolve_type_expression(
+ ast_context,
+ s.types[i],
+ )
+ symbol.type = .Variable
+ return symbol, ok
+ }
+ }
case SymbolPackageValue:
try_build_package(ast_context.current_package)
@@ -1309,6 +1374,10 @@ internal_resolve_type_identifier :: proc(
return_symbol, ok =
make_symbol_bitset_from_ast(ast_context, v^, node), true
return_symbol.name = node.name
+ case ^Bit_Field_Type:
+ return_symbol, ok =
+ make_symbol_bit_field_from_ast(ast_context, v^, node), true
+ return_symbol.name = node.name
case ^Proc_Lit:
if !is_procedure_generic(v.type) {
return_symbol, ok =
@@ -1441,6 +1510,15 @@ internal_resolve_type_identifier :: proc(
return_symbol, ok =
make_symbol_enum_from_ast(ast_context, v^, node), true
return_symbol.name = node.name
+ case ^Bit_Field_Type:
+ return_symbol, ok =
+ make_symbol_bit_field_from_ast(
+ ast_context,
+ v^,
+ node,
+ ),
+ true
+ return_symbol.name = node.name
case ^Proc_Lit:
if !is_procedure_generic(v.type) {
return_symbol, ok =
@@ -1911,6 +1989,34 @@ resolve_implicit_selector :: proc(
}
return resolve_type_expression(ast_context, type)
+ } else if s, ok := comp_symbol.value.(SymbolBitFieldValue); ok {
+ ast_context.current_package = comp_symbol.pkg
+
+ //We can either have the final
+ elem_index := -1
+
+ for elem, i in comp_lit.elems {
+ if position_in_node(elem, position_context.position) {
+ elem_index = i
+ }
+ }
+
+ type: ^ast.Expr
+
+ for name, i in s.names {
+ if name != field_name {
+ continue
+ }
+
+ type = s.types[i]
+ break
+ }
+
+ if type == nil && len(s.types) > elem_index {
+ type = s.types[elem_index]
+ }
+
+ return resolve_type_expression(ast_context, type)
}
}
}
@@ -2018,7 +2124,7 @@ resolve_unresolved_symbol :: proc(
}
#partial switch v in symbol.value {
- case SymbolStructValue:
+ case SymbolStructValue, SymbolBitFieldValue:
symbol.type = .Struct
case SymbolPackageValue:
symbol.type = .Package
@@ -2105,7 +2211,12 @@ resolve_location_comp_lit_field :: proc(
if name == field.name {
symbol.range = struct_value.ranges[i]
}
-
+ }
+ } else if bit_field_value, ok := symbol.value.(SymbolBitFieldValue); ok {
+ for name, i in bit_field_value.names {
+ if name == field.name {
+ symbol.range = bit_field_value.ranges[i]
+ }
}
}
@@ -2170,6 +2281,12 @@ resolve_location_selector :: proc(
symbol.range = v.ranges[i]
}
}
+ case SymbolBitFieldValue:
+ for name, i in v.names {
+ if strings.compare(name, field) == 0 {
+ symbol.range = v.ranges[i]
+ }
+ }
case SymbolPackageValue:
if pkg, ok := lookup(field, symbol.pkg); ok {
symbol.range = pkg.range
@@ -2838,6 +2955,49 @@ make_symbol_struct_from_ast :: proc(
return symbol
}
+make_symbol_bit_field_from_ast :: proc(
+ ast_context: ^AstContext,
+ v: ast.Bit_Field_Type,
+ ident: ast.Ident,
+ inlined := false,
+) -> Symbol {
+ symbol := Symbol {
+ range = common.get_token_range(v, ast_context.file.src),
+ type = .Struct,
+ pkg = get_package_from_node(v.node),
+ name = ident.name,
+ }
+
+ if inlined {
+ symbol.flags |= {.Anonymous}
+ symbol.name = "bit_field"
+ }
+
+ names := make([dynamic]string, ast_context.allocator)
+ types := make([dynamic]^ast.Expr, ast_context.allocator)
+ ranges := make([dynamic]common.Range, 0, ast_context.allocator)
+
+ for field in v.fields {
+ if identifier, ok := field.name.derived.(^ast.Ident);
+ ok && field.type != nil {
+ append(&names, identifier.name)
+ append(&types, field.type)
+ append(
+ &ranges,
+ common.get_token_range(identifier, ast_context.file.src),
+ )
+ }
+ }
+
+ symbol.value = SymbolBitFieldValue {
+ names = names[:],
+ types = types[:],
+ ranges = ranges[:],
+ }
+
+ return symbol
+}
+
get_globals :: proc(file: ast.File, ast_context: ^AstContext) {
exprs := common.collect_globals(file)
@@ -3075,7 +3235,7 @@ get_locals_block_stmt :: proc(
}
get_locals_using :: proc(expr: ^ast.Expr, ast_context: ^AstContext) {
- if symbol, expr, ok := unwrap_procedure_until_struct_or_package(
+ if symbol, expr, ok := unwrap_procedure_until_struct_bit_field_or_package(
ast_context,
expr,
); ok {
@@ -3114,6 +3274,36 @@ get_locals_using :: proc(expr: ^ast.Expr, ast_context: ^AstContext) {
false,
)
}
+ case SymbolBitFieldValue:
+ for name, i in v.names {
+ selector := new_type(
+ ast.Selector_Expr,
+ v.types[i].pos,
+ v.types[i].end,
+ ast_context.allocator,
+ )
+ selector.expr = expr
+ selector.field = new_type(
+ ast.Ident,
+ v.types[i].pos,
+ v.types[i].end,
+ ast_context.allocator,
+ )
+ selector.field.name = name
+ store_local(
+ ast_context,
+ expr,
+ selector,
+ 0,
+ name,
+ ast_context.local_id,
+ false,
+ ast_context.non_mutable_only,
+ true,
+ "",
+ false,
+ )
+ }
}
}
}
@@ -3927,7 +4117,7 @@ concatenate_raw_string_information :: proc(
}
}
-unwrap_procedure_until_struct_or_package :: proc(
+unwrap_procedure_until_struct_bit_field_or_package :: proc(
ast_context: ^AstContext,
node: ^ast.Expr,
) -> (
@@ -3964,7 +4154,7 @@ unwrap_procedure_until_struct_or_package :: proc(
}
expr = v.return_types[0].type
- case SymbolStructValue, SymbolPackageValue:
+ case SymbolStructValue, SymbolPackageValue, SymbolBitFieldValue:
ok = true
return
case:
@@ -4124,6 +4314,15 @@ get_signature :: proc(
} else {
return "union"
}
+ case SymbolBitFieldValue:
+ if is_variable {
+ return strings.concatenate(
+ {pointer_prefix, symbol.name},
+ ast_context.allocator,
+ )
+ } else {
+ return "bit_field"
+ }
case SymbolMultiPointer:
return strings.concatenate(
a = {pointer_prefix, "[^]", common.node_to_string(v.expr)},
@@ -5084,6 +5283,14 @@ get_document_position_node :: proc(
get_document_position(n.y, position_context)
case ^ast.Or_Return_Expr:
get_document_position(n.expr, position_context)
+ case ^ast.Bit_Field_Type:
+ position_context.bit_field_type = cast(^Bit_Field_Type)node
+ get_document_position(n.backing_type, position_context)
+ get_document_position(n.fields, position_context)
+ case ^ast.Bit_Field_Field:
+ get_document_position(n.name, position_context)
+ get_document_position(n.type, position_context)
+ get_document_position(n.bit_size, position_context)
case:
}
}
diff --git a/src/server/clone.odin b/src/server/clone.odin
index 796bf33..d535d19 100644
--- a/src/server/clone.odin
+++ b/src/server/clone.odin
@@ -287,6 +287,13 @@ clone_node :: proc(
case ^Relative_Type:
r.tag = clone_type(r.tag, allocator, unique_strings)
r.type = clone_type(r.type, allocator, unique_strings)
+ case ^Bit_Field_Type:
+ r.backing_type = clone_type(r.backing_type, allocator, unique_strings)
+ r.fields = clone_type(r.fields, allocator, unique_strings)
+ case ^Bit_Field_Field:
+ r.name = clone_type(r.name, allocator, unique_strings)
+ r.type = clone_type(r.type, allocator, unique_strings)
+ r.bit_size = clone_type(r.bit_size, allocator, unique_strings)
case:
}
diff --git a/src/server/collector.odin b/src/server/collector.odin
index 33c4822..fde4f30 100644
--- a/src/server/collector.odin
+++ b/src/server/collector.odin
@@ -191,6 +191,41 @@ collect_struct_fields :: proc(
return value
}
+collect_bit_field_fields :: proc(
+ collection: ^SymbolCollection,
+ fields: []^ast.Bit_Field_Field,
+ package_map: map[string]string,
+ file: ast.File,
+) -> SymbolBitFieldValue {
+ names := make([dynamic]string, 0, len(fields), collection.allocator)
+ types := make([dynamic]^ast.Expr, 0, len(fields), collection.allocator)
+ ranges := make([dynamic]common.Range, 0, len(fields), collection.allocator)
+
+ for field, i in fields {
+ if ident, ok := field.name.derived.(^ast.Ident); ok {
+ append(&names, get_index_unique_string(collection, ident.name))
+
+ cloned := clone_type(
+ field.type,
+ collection.allocator,
+ &collection.unique_strings,
+ )
+ replace_package_alias(cloned, package_map, collection)
+ append(&types, cloned)
+
+ append(&ranges, common.get_token_range(ident, file.src))
+ }
+ }
+
+ value := SymbolBitFieldValue {
+ names = names[:],
+ types = types[:],
+ ranges = ranges[:],
+ }
+
+ return value
+}
+
collect_enum_fields :: proc(
collection: ^SymbolCollection,
fields: []^ast.Expr,
@@ -648,6 +683,16 @@ collect_symbols :: proc(
token_type = .Enum
symbol.value = collect_bitset_field(collection, v^, package_map)
symbol.signature = "bitset"
+ case ^ast.Bit_Field_Type:
+ token = v^
+ token_type = .Struct
+ symbol.value = collect_bit_field_fields(
+ collection,
+ v.fields,
+ package_map,
+ file,
+ )
+ symbol.signature = "bit_field"
case ^ast.Map_Type:
token = v^
token_type = .Variable
@@ -999,6 +1044,13 @@ replace_package_alias_node :: proc(
case ^Proc_Lit:
case ^Multi_Pointer_Type:
replace_package_alias(n.elem, package_map, collection)
+ case ^Bit_Field_Type:
+ replace_package_alias(n.backing_type, package_map, collection)
+ replace_package_alias(n.fields, package_map, collection)
+ case ^Bit_Field_Field:
+ replace_package_alias(n.name, package_map, collection)
+ replace_package_alias(n.type, package_map, collection)
+ replace_package_alias(n.bit_size, package_map, collection)
case:
}
}
diff --git a/src/server/completion.odin b/src/server/completion.odin
index caba5bf..f917498 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -260,7 +260,40 @@ get_comp_lit_completion :: proc(
append(&items, item)
}
}
+ case SymbolBitFieldValue:
+ for name, i in v.names {
+ if name == "_" {
+ continue
+ }
+
+ ast_context.current_package = symbol.pkg
+
+ if resolved, ok := resolve_type_expression(
+ ast_context,
+ v.types[i],
+ ); ok {
+ if field_exists_in_comp_lit(
+ position_context.comp_lit,
+ name,
+ ) {
+ continue
+ }
+ item := CompletionItem {
+ label = name,
+ kind = .Field,
+ detail = fmt.tprintf(
+ "%v.%v: %v",
+ symbol.name,
+ name,
+ common.node_to_string(v.types[i]),
+ ),
+ documentation = resolved.doc,
+ }
+
+ append(&items, item)
+ }
+ }
}
}
@@ -609,6 +642,52 @@ get_selector_completion :: proc(
}
}
+ case SymbolBitFieldValue:
+ list.isIncomplete = false
+
+ for name, i in v.names {
+ if name == "_" {
+ continue
+ }
+
+ if selector.pkg != "" {
+ ast_context.current_package = selector.pkg
+ } else {
+ ast_context.current_package = ast_context.document_package
+ }
+
+ if symbol, ok := resolve_type_expression(ast_context, v.types[i]);
+ ok {
+ item := CompletionItem {
+ label = name,
+ kind = .Field,
+ detail = fmt.tprintf(
+ "%v.%v: %v",
+ selector.name,
+ name,
+ type_to_string(ast_context, v.types[i]),
+ ),
+ documentation = symbol.doc,
+ }
+
+ append(&items, item)
+ } else {
+ //just give some generic symbol with name.
+ item := CompletionItem {
+ label = symbol.name,
+ kind = .Field,
+ detail = fmt.tprintf(
+ "%v: %v",
+ name,
+ common.node_to_string(v.types[i]),
+ ),
+ documentation = symbol.doc,
+ }
+
+ append(&items, item)
+ }
+ }
+
case SymbolPackageValue:
list.isIncomplete = true
diff --git a/src/server/document_symbols.odin b/src/server/document_symbols.odin
index 334bb6e..8a0cb2d 100644
--- a/src/server/document_symbols.odin
+++ b/src/server/document_symbols.odin
@@ -62,7 +62,7 @@ get_document_symbols :: proc(document: ^Document) -> []DocumentSymbol {
symbol.name = k
#partial switch v in global.expr.derived {
- case ^ast.Struct_Type:
+ case ^ast.Struct_Type, ^ast.Bit_Field_Type:
symbol.kind = .Struct
case ^ast.Proc_Lit, ^ast.Proc_Group:
symbol.kind = .Function
diff --git a/src/server/hover.odin b/src/server/hover.odin
index c3dccbc..566b41c 100644
--- a/src/server/hover.odin
+++ b/src/server/hover.odin
@@ -165,6 +165,26 @@ get_hover_information :: proc(
}
}
}
+ } else if v, ok := comp_symbol.value.(SymbolBitFieldValue); ok {
+ for name, i in v.names {
+ if name == field.name {
+ if symbol, ok := resolve_type_expression(
+ &ast_context,
+ v.types[i],
+ ); ok {
+ symbol.name = name
+ symbol.pkg = comp_symbol.name
+ symbol.signature = common.node_to_string(
+ v.types[i],
+ )
+ hover.contents = write_hover_content(
+ &ast_context,
+ symbol,
+ )
+ return hover, true, true
+ }
+ }
+ }
}
}
}
@@ -268,6 +288,24 @@ get_hover_information :: proc(
}
}
}
+ case SymbolBitFieldValue:
+ for name, i in v.names {
+ if name == field {
+ if symbol, ok := resolve_type_expression(
+ &ast_context,
+ v.types[i],
+ ); ok {
+ symbol.name = name
+ symbol.pkg = selector.name
+ symbol.signature = common.node_to_string(v.types[i])
+ hover.contents = write_hover_content(
+ &ast_context,
+ symbol,
+ )
+ return hover, true, true
+ }
+ }
+ }
case SymbolPackageValue:
if position_context.field != nil {
if ident, ok := position_context.field.derived.(^ast.Ident);
diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin
index 7fafc21..643709c 100644
--- a/src/server/semantic_tokens.odin
+++ b/src/server/semantic_tokens.odin
@@ -759,6 +759,16 @@ visit_node :: proc(
visit_proc_type(n.type, builder, ast_context)
visit(n.body, builder, ast_context)
+ case ^Bit_Field_Type:
+ write_semantic_string(
+ builder,
+ n.pos,
+ "bit_field",
+ ast_context.file.src,
+ .Keyword,
+ .None,
+ )
+ visit_bit_field_fields(n^, builder, ast_context)
case:
}
}
@@ -1050,6 +1060,27 @@ visit_struct_fields :: proc(
}
}
+visit_bit_field_fields :: proc(
+ node: ast.Bit_Field_Type,
+ builder: ^SemanticTokenBuilder,
+ ast_context: ^AstContext,
+) {
+ for field in node.fields {
+ if ident, ok := field.name.derived.(^ast.Ident); ok {
+ write_semantic_node(
+ builder,
+ ident,
+ ast_context.file.src,
+ .Property,
+ .None,
+ )
+ }
+
+ visit(field.type, builder, ast_context)
+ visit(field.bit_size, builder, ast_context)
+ }
+}
+
visit_selector :: proc(
selector: ^ast.Selector_Expr,
builder: ^SemanticTokenBuilder,
@@ -1125,6 +1156,14 @@ visit_selector :: proc(
.Function,
.None,
)
+ case SymbolBitFieldValue:
+ write_semantic_node(
+ builder,
+ selector.field,
+ ast_context.file.src,
+ .Struct,
+ .None,
+ )
}
}
}
diff --git a/src/server/symbol.odin b/src/server/symbol.odin
index 10750a8..31c5fa8 100644
--- a/src/server/symbol.odin
+++ b/src/server/symbol.odin
@@ -28,6 +28,12 @@ SymbolStructValue :: struct {
args: []^ast.Expr, //The arguments in the call expression for poly
}
+SymbolBitFieldValue :: struct {
+ names: []string,
+ ranges: []common.Range,
+ types: []^ast.Expr,
+}
+
SymbolPackageValue :: struct {}
SymbolProcedureValue :: struct {
@@ -126,6 +132,7 @@ SymbolValue :: union {
SymbolBasicValue,
SymbolUntypedValue,
SymbolMatrixValue,
+ SymbolBitFieldValue,
}
SymbolFlag :: enum {
@@ -185,7 +192,8 @@ free_symbol :: proc(symbol: Symbol, allocator: mem.Allocator) {
symbol.signature != "struct" &&
symbol.signature != "union" &&
symbol.signature != "enum" &&
- symbol.signature != "bitset" {
+ symbol.signature != "bitset" &&
+ symbol.signature != "bit_field" {
delete(symbol.signature, allocator)
}
@@ -235,6 +243,9 @@ free_symbol :: proc(symbol: Symbol, allocator: mem.Allocator) {
case SymbolUntypedValue:
delete(v.tok.text)
case SymbolPackageValue:
+ case SymbolBitFieldValue:
+ delete(v.names, allocator)
+ common.free_ast(v.types, allocator)
}
}
@@ -346,6 +357,9 @@ symbol_to_expr :: proc(
type.params = new_type(ast.Field_List, pos, end, allocator)
type.params.list = v.arg_types
return type
+ case SymbolBitFieldValue:
+ type := new_type(ast.Bit_Field_Type, pos, end, allocator)
+ return type
case:
return nil
}