aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorDamian Tarnawski <gthetarnav@gmail.com>2024-04-27 22:13:05 +0200
committerDamian Tarnawski <gthetarnav@gmail.com>2024-04-27 22:13:05 +0200
commit0ca38c9f44b47c87ae9e810087eabec0f01c0d9c (patch)
treecdae1aa9d17325d76b5085e3f627d3619820cd8d /src/server
parent708dca6147e21e471c3c44856bd650ce7f5ede60 (diff)
Simplify and improve semantic tokens system further
- Remove the remaining tokens for operators, those will be handled by syntax highlighting - Improve `visit_value_decl` mostly around making aliases: ```odin foo :: proc() {} bar :: foo ``` now `bar` will be highlighted as a `.Function` - Add `src` to `SemanticTokenBuilder` to avoid it being passed around to every proc - Tried to reduce the amount of procedures and repeated code Now most of the work is done by `visit_node`, which walks the ast looking for identifiers, and `visit_ident`, which writes the token for that identifier based on it's symbol
Diffstat (limited to 'src/server')
-rw-r--r--src/server/semantic_tokens.odin881
1 files changed, 240 insertions, 641 deletions
diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin
index 95e286b..bd95d48 100644
--- a/src/server/semantic_tokens.odin
+++ b/src/server/semantic_tokens.odin
@@ -109,16 +109,7 @@ SemanticTokenBuilder :: struct {
tokens: [dynamic]u32,
symbols: map[uintptr]SymbolAndNode,
selector: bool,
-}
-
-make_token_builder :: proc(
- allocator := context.temp_allocator,
-) -> SemanticTokenBuilder {
- return {tokens = make([dynamic]u32, 10000, context.temp_allocator)}
-}
-
-get_tokens :: proc(builder: SemanticTokenBuilder) -> SemanticTokens {
- return {data = builder.tokens[:]}
+ src: string,
}
get_semantic_tokens :: proc(
@@ -126,8 +117,6 @@ get_semantic_tokens :: proc(
range: common.Range,
symbols: map[uintptr]SymbolAndNode,
) -> SemanticTokens {
- builder := make_token_builder()
-
ast_context := make_ast_context(
document.ast,
document.imports,
@@ -135,137 +124,91 @@ get_semantic_tokens :: proc(
document.uri.uri,
document.fullpath,
)
-
- builder.symbols = symbols
-
ast_context.current_package = ast_context.document_package
+ builder: SemanticTokenBuilder = {
+ tokens = make([dynamic]u32, 10000, context.temp_allocator),
+ symbols = symbols,
+ src = ast_context.file.src,
+ }
+
for decl in document.ast.decls {
if range.start.line <= decl.pos.line &&
decl.end.line <= range.end.line {
- visit(decl, &builder, &ast_context)
+ visit_node(decl, &builder)
}
}
- return get_tokens(builder)
+ return {data = builder.tokens[:]}
}
-write_semantic_node :: proc(
+write_semantic_at_pos :: proc(
builder: ^SemanticTokenBuilder,
- node: ^ast.Node,
- src: string,
+ pos: int,
+ len: int,
type: SemanticTokenTypes,
modifiers: SemanticTokenModifiers = {},
) {
- //Sometimes odin ast uses "_" for empty params.
- if ident, ok := node.derived.(^ast.Ident); ok && ident.name == "_" {
- return
- }
-
position := common.get_relative_token_position(
- node.pos.offset,
- transmute([]u8)src,
+ pos,
+ transmute([]u8)builder.src,
builder.current_start,
)
- name := common.get_ast_node_string(node, src)
append(
&builder.tokens,
cast(u32)position.line,
cast(u32)position.character,
- cast(u32)len(name),
+ cast(u32)len,
cast(u32)type,
transmute(u32)modifiers,
)
- builder.current_start = node.pos.offset
+ builder.current_start = pos
}
-write_semantic_token :: proc(
+write_semantic_node :: proc(
builder: ^SemanticTokenBuilder,
- token: tokenizer.Token,
- src: string,
+ node: ^ast.Node,
type: SemanticTokenTypes,
modifiers: SemanticTokenModifiers = {},
) {
- position := common.get_relative_token_position(
- token.pos.offset,
- transmute([]u8)src,
- builder.current_start,
- )
- append(
- &builder.tokens,
- cast(u32)position.line,
- cast(u32)position.character,
- cast(u32)len(token.text),
- cast(u32)type,
- transmute(u32)modifiers,
+ //Sometimes odin ast uses "_" for empty params.
+ if ident, ok := node.derived.(^ast.Ident); ok && ident.name == "_" {
+ return
+ }
+
+ name := common.get_ast_node_string(node, builder.src)
+
+ write_semantic_at_pos(
+ builder,
+ node.pos.offset,
+ len(name),
+ type,
+ modifiers,
)
- builder.current_start = token.pos.offset
}
-write_semantic_string :: proc(
+write_semantic_token :: proc(
builder: ^SemanticTokenBuilder,
- pos: tokenizer.Pos,
- name: string,
- src: string,
+ token: tokenizer.Token,
type: SemanticTokenTypes,
modifiers: SemanticTokenModifiers = {},
) {
- position := common.get_relative_token_position(
- pos.offset,
- transmute([]u8)src,
- builder.current_start,
- )
- append(
- &builder.tokens,
- cast(u32)position.line,
- cast(u32)position.character,
- cast(u32)len(name),
- cast(u32)type,
- transmute(u32)modifiers,
+ write_semantic_at_pos(
+ builder,
+ token.pos.offset,
+ len(token.text),
+ type,
+ modifiers,
)
- builder.current_start = pos.offset
-}
-
-visit :: proc {
- visit_node,
- visit_dynamic_array,
- visit_array,
- visit_stmt,
-}
-
-visit_array :: proc(
- array: $A/[]^$T,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
- for elem, i in array {
- visit(elem, builder, ast_context)
- }
}
-visit_dynamic_array :: proc(
- array: $A/[dynamic]^$T,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
- for elem, i in array {
- visit(elem, builder, ast_context)
+visit_nodes :: proc(array: []$T/^ast.Node, builder: ^SemanticTokenBuilder) {
+ for elem in array {
+ visit_node(elem, builder)
}
}
-visit_stmt :: proc(
- node: ^ast.Stmt,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
- visit_node(node, builder, ast_context)
-}
-
-visit_node :: proc(
- node: ^ast.Node,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
+visit_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder) {
using ast
if node == nil {
@@ -274,509 +217,203 @@ visit_node :: proc(
#partial switch n in node.derived {
case ^Ellipsis:
- visit(n.expr, builder, ast_context)
+ visit_node(n.expr, builder)
case ^Ident:
- modifiers: SemanticTokenModifiers
-
- symbol_and_node := builder.symbols[cast(uintptr)node] or_break
-
- if symbol_and_node.symbol.type == .Constant ||
- symbol_and_node.symbol.type != .Variable {
- modifiers += {.ReadOnly}
- }
-
- if .Distinct in symbol_and_node.symbol.flags &&
- symbol_and_node.symbol.type == .Constant {
- write_semantic_node(
- builder,
- node,
- ast_context.file.src,
- .Type,
- )
- return
- }
-
- #partial switch symbol_and_node.symbol.type {
- case .Variable, .Constant:
- #partial switch _ in symbol_and_node.symbol.value {
- case SymbolProcedureValue:
- write_semantic_node(
- builder,
- node,
- ast_context.file.src,
- .Function,
- modifiers,
- )
- case:
- write_semantic_node(
- builder,
- node,
- ast_context.file.src,
- .Variable,
- modifiers,
- )
- }
- case .Type_Function:
- write_semantic_node(
- builder,
- node,
- ast_context.file.src,
- .Type,
- modifiers,
- )
- }
-
- switch v in symbol_and_node.symbol.value {
- case SymbolPackageValue:
- write_semantic_node(
- builder,
- node,
- ast_context.file.src,
- .Namespace,
- )
- case SymbolStructValue,
- SymbolBitFieldValue:
- write_semantic_node(
- builder,
- node,
- ast_context.file.src,
- .Struct,
- modifiers,
- )
- case SymbolEnumValue,
- SymbolUnionValue:
- write_semantic_node(
- builder,
- node,
- ast_context.file.src,
- .Enum,
- modifiers,
- )
- case SymbolProcedureValue,
- SymbolProcedureGroupValue,
- SymbolAggregateValue:
- write_semantic_node(
- builder,
- node,
- ast_context.file.src,
- .Function,
- modifiers,
- )
- case SymbolMatrixValue,
- SymbolBitSetValue,
- SymbolDynamicArrayValue,
- SymbolFixedArrayValue,
- SymbolSliceValue,
- SymbolMapValue,
- SymbolMultiPointer:
- write_semantic_node(
- builder,
- node,
- ast_context.file.src,
- .Type,
- modifiers,
- )
- case SymbolBasicValue, SymbolUntypedValue:
- // handled by static syntax analysis
- case SymbolGenericValue:
- // unused
- case:
- //log.errorf("Unexpected symbol value: %v", symbol.value);
- //panic(fmt.tprintf("Unexpected symbol value: %v", symbol.value));
- }
+ visit_ident(n, {}, builder)
case ^Selector_Expr:
- visit_selector(cast(^Selector_Expr)node, builder, ast_context)
+ visit_selector(cast(^Selector_Expr)node, builder)
builder.selector = false
case ^When_Stmt:
- visit(n.cond, builder, ast_context)
- visit(n.body, builder, ast_context)
- visit(n.else_stmt, builder, ast_context)
+ visit_node(n.cond, builder)
+ visit_node(n.body, builder)
+ visit_node(n.else_stmt, builder)
case ^Pointer_Type:
- write_semantic_string(
- builder,
- node.pos,
- "^",
- ast_context.file.src,
- .Operator,
- )
- visit(n.elem, builder, ast_context)
+ visit_node(n.elem, builder)
case ^Value_Decl:
- visit_value_decl(n^, builder, ast_context)
+ visit_value_decl(n^, builder)
case ^Block_Stmt:
- visit(n.stmts, builder, ast_context)
- case ^ast.Foreign_Block_Decl:
- visit(n.body, builder, ast_context)
+ visit_nodes(n.stmts, builder)
+ case ^Foreign_Block_Decl:
+ visit_node(n.body, builder)
case ^Expr_Stmt:
- visit(n.expr, builder, ast_context)
+ visit_node(n.expr, builder)
case ^Matrix_Type:
- visit(n.row_count, builder, ast_context)
- visit(n.column_count, builder, ast_context)
- visit(n.elem, builder, ast_context)
- case ^ast.Matrix_Index_Expr:
- visit(n.expr, builder, ast_context)
- visit(n.row_index, builder, ast_context)
- visit(n.column_index, builder, ast_context)
+ visit_node(n.row_count, builder)
+ visit_node(n.column_count, builder)
+ visit_node(n.elem, builder)
+ case ^Matrix_Index_Expr:
+ visit_node(n.expr, builder)
+ visit_node(n.row_index, builder)
+ visit_node(n.column_index, builder)
case ^Poly_Type:
- write_semantic_string(
- builder,
- n.dollar,
- "$",
- ast_context.file.src,
- .Operator,
- )
- visit(n.type, builder, ast_context)
- visit(n.specialization, builder, ast_context)
+ visit_node(n.type, builder)
+ visit_node(n.specialization, builder)
case ^Range_Stmt:
for val in n.vals {
if ident, ok := val.derived.(^Ident); ok {
- write_semantic_node(
- builder,
- val,
- ast_context.file.src,
- .Variable,
- )
+ write_semantic_node(builder, val, .Variable)
}
}
- visit(n.expr, builder, ast_context)
- visit(n.body, builder, ast_context)
+ visit_node(n.expr, builder)
+ visit_node(n.body, builder)
case ^If_Stmt:
- visit(n.init, builder, ast_context)
- visit(n.cond, builder, ast_context)
- visit(n.body, builder, ast_context)
+ visit_node(n.init, builder)
+ visit_node(n.cond, builder)
+ visit_node(n.body, builder)
if n.else_stmt != nil {
- visit(n.else_stmt, builder, ast_context)
+ visit_node(n.else_stmt, builder)
}
case ^For_Stmt:
- visit(n.init, builder, ast_context)
- visit(n.cond, builder, ast_context)
- visit(n.post, builder, ast_context)
- visit(n.body, builder, ast_context)
+ visit_node(n.init, builder)
+ visit_node(n.cond, builder)
+ visit_node(n.post, builder)
+ visit_node(n.body, builder)
case ^Switch_Stmt:
- visit(n.init, builder, ast_context)
- visit(n.cond, builder, ast_context)
- visit(n.body, builder, ast_context)
+ visit_node(n.init, builder)
+ visit_node(n.cond, builder)
+ visit_node(n.body, builder)
case ^Type_Switch_Stmt:
- visit(n.tag, builder, ast_context)
- visit(n.expr, builder, ast_context)
- visit(n.body, builder, ast_context)
+ visit_node(n.tag, builder)
+ visit_node(n.expr, builder)
+ visit_node(n.body, builder)
case ^Assign_Stmt:
for l in n.lhs {
if ident, ok := l.derived.(^Ident); ok {
- write_semantic_node(
- builder,
- l,
- ast_context.file.src,
- .Variable,
- )
+ write_semantic_node(builder, l, .Variable)
} else {
- visit(l, builder, ast_context)
+ visit_node(l, builder)
}
}
-
- visit_token_op(builder, n.op, ast_context.file.src)
- visit(n.rhs, builder, ast_context)
+ visit_nodes(n.rhs, builder)
case ^Case_Clause:
- visit(n.list, builder, ast_context)
- visit(n.body, builder, ast_context)
+ visit_nodes(n.list, builder)
+ visit_nodes(n.body, builder)
case ^Call_Expr:
- visit(n.expr, builder, ast_context)
- visit(n.args, builder, ast_context)
+ visit_node(n.expr, builder)
+ visit_nodes(n.args, builder)
case ^Implicit_Selector_Expr:
write_semantic_node(
builder,
n.field,
- ast_context.file.src,
.EnumMember,
)
case ^Array_Type:
- visit(n.len, builder, ast_context)
- visit(n.elem, builder, ast_context)
+ visit_node(n.len, builder)
+ visit_node(n.elem, builder)
case ^Binary_Expr:
- visit(n.left, builder, ast_context)
- visit_token_op(builder, n.op, ast_context.file.src)
- visit(n.right, builder, ast_context)
+ visit_node(n.left, builder)
+ visit_node(n.right, builder)
case ^Comp_Lit:
- visit(n.type, builder, ast_context)
- visit(n.elems, builder, ast_context)
+ visit_node(n.type, builder)
+ visit_nodes(n.elems, builder)
case ^Struct_Type:
- visit_struct_fields(n^, builder, ast_context)
+ visit_struct_fields(n^, builder)
case ^Type_Assertion:
- visit(n.expr, builder, ast_context)
- visit(n.type, builder, ast_context)
+ visit_node(n.expr, builder)
+ visit_node(n.type, builder)
case ^Type_Cast:
- visit(n.type, builder, ast_context)
- visit(n.expr, builder, ast_context)
+ visit_node(n.type, builder)
+ visit_node(n.expr, builder)
case ^Paren_Expr:
- visit(n.expr, builder, ast_context)
+ visit_node(n.expr, builder)
case ^Deref_Expr:
- visit(n.expr, builder, ast_context)
+ visit_node(n.expr, builder)
case ^Return_Stmt:
- visit(n.results, builder, ast_context)
+ visit_nodes(n.results, builder)
case ^Dynamic_Array_Type:
- visit(n.elem, builder, ast_context)
+ visit_node(n.elem, builder)
case ^Multi_Pointer_Type:
- visit(n.elem, builder, ast_context)
+ visit_node(n.elem, builder)
case ^Field_Value:
if ident, ok := n.field.derived.(^Ident); ok {
- write_semantic_node(
- builder,
- n.field,
- ast_context.file.src,
- .Property,
- )
+ write_semantic_node(builder, n.field, .Property)
} else {
- visit(n.field, builder, ast_context)
+ visit_node(n.field, builder)
}
- visit(n.value, builder, ast_context)
+ visit_node(n.value, builder)
case ^Index_Expr:
- visit(n.expr, builder, ast_context)
- visit(n.index, builder, ast_context)
- case ^Basic_Lit:
- visit_basic_lit(n^, builder, ast_context)
+ visit_node(n.expr, builder)
+ visit_node(n.index, builder)
case ^Unary_Expr:
- visit(n.expr, builder, ast_context)
+ visit_node(n.expr, builder)
case ^Implicit:
case ^Slice_Expr:
- visit(n.expr, builder, ast_context)
+ visit_node(n.expr, builder)
case ^Using_Stmt:
- visit(n.list, builder, ast_context)
+ visit_nodes(n.list, builder)
case ^Map_Type:
- visit(n.key, builder, ast_context)
- visit(n.value, builder, ast_context)
+ visit_node(n.key, builder)
+ visit_node(n.value, builder)
case ^Bit_Set_Type:
- visit(n.elem, builder, ast_context)
- visit(n.underlying, builder, ast_context)
+ visit_node(n.elem, builder)
+ visit_node(n.underlying, builder)
case ^Defer_Stmt:
- visit(n.stmt, builder, ast_context)
+ visit_node(n.stmt, builder)
case ^Import_Decl:
if n.name.text != "" {
- write_semantic_token(
- builder,
- n.name,
- ast_context.file.src,
- .Namespace,
- )
+ write_semantic_token(builder, n.name, .Namespace)
}
case ^Or_Return_Expr:
- visit(n.expr, builder, ast_context)
+ visit_node(n.expr, builder)
case ^Or_Else_Expr:
- visit(n.x, builder, ast_context)
- visit(n.y, builder, ast_context)
+ visit_node(n.x, builder)
+ visit_node(n.y, builder)
case ^Ternary_If_Expr:
if n.op1.text == "if" {
- visit(n.x, builder, ast_context)
- visit(n.cond, builder, ast_context)
- visit(n.y, builder, ast_context)
+ visit_node(n.x, builder)
+ visit_node(n.cond, builder)
+ visit_node(n.y, builder)
} else {
- visit(n.cond, builder, ast_context)
- visit(n.x, builder, ast_context)
- visit(n.y, builder, ast_context)
+ visit_node(n.cond, builder)
+ visit_node(n.x, builder)
+ visit_node(n.y, builder)
}
case ^Ternary_When_Expr:
- visit(n.cond, builder, ast_context)
- visit(n.x, builder, ast_context)
- visit(n.y, builder, ast_context)
+ visit_node(n.cond, builder)
+ visit_node(n.x, builder)
+ visit_node(n.y, builder)
case ^Union_Type:
- visit(n.variants, builder, ast_context)
- case ^ast.Enum_Type:
- visit_enum_fields(n^, builder, ast_context)
+ visit_nodes(n.variants, builder)
+ case ^Enum_Type:
+ visit_enum_fields(n^, builder)
case ^Proc_Type:
- visit_proc_type(n, builder, ast_context)
+ visit_proc_type(n, builder)
case ^Proc_Lit:
- visit_proc_type(n.type, builder, ast_context)
-
- visit(n.body, builder, ast_context)
+ visit_proc_type(n.type, builder)
+ visit_node(n.body, builder)
+ case ^Proc_Group:
+ for arg in n.args {
+ ident := arg.derived.(^Ident) or_continue
+ write_semantic_node(builder, arg, .Function)
+ }
case ^Bit_Field_Type:
- visit_bit_field_fields(n^, builder, ast_context)
+ visit_bit_field_fields(n^, builder)
case:
}
}
-visit_basic_lit :: proc(
- basic_lit: ast.Basic_Lit,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
- if symbol, ok := resolve_basic_lit(ast_context, basic_lit); ok {
- if untyped, ok := symbol.value.(SymbolUntypedValue); ok {
- #partial switch untyped.type {
- case .Bool:
- write_semantic_token(
- builder,
- basic_lit.tok,
- ast_context.file.src,
- .Keyword,
- )
- case .Float, .Integer:
- write_semantic_token(
- builder,
- basic_lit.tok,
- ast_context.file.src,
- .Number,
- )
- }
- }
- }
-}
-
-visit_value_decl :: proc(
- value_decl: ast.Value_Decl,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
+visit_value_decl :: proc(value_decl: ast.Value_Decl, builder: ^SemanticTokenBuilder) {
using ast
modifiers: SemanticTokenModifiers = value_decl.is_mutable ? {} : {.ReadOnly}
-
- if value_decl.type != nil {
- for name in value_decl.names {
- write_semantic_node(
- builder,
- name,
- ast_context.file.src,
- .Variable,
- modifiers,
- )
- }
-
- visit(value_decl.type, builder, ast_context)
-
- if len(value_decl.values) == 1 {
- visit(value_decl.values[0], builder, ast_context)
- }
-
- return
- }
-
- if len(value_decl.values) != 1 {
- for name in value_decl.names {
- write_semantic_node(
- builder,
- name,
- ast_context.file.src,
- .Variable,
- modifiers,
- )
- }
-
- for value in value_decl.values {
- visit(value, builder, ast_context)
- }
+
+ for name in value_decl.names {
+ ident := name.derived.(^Ident) or_continue
+ visit_ident(ident, modifiers, builder)
}
- #partial switch v in value_decl.values[0].derived {
- case ^Union_Type:
- write_semantic_node(
- builder,
- value_decl.names[0],
- ast_context.file.src,
- .Enum,
- modifiers,
- )
- visit(value_decl.values[0], builder, ast_context)
- case ^Struct_Type:
- write_semantic_node(
- builder,
- value_decl.names[0],
- ast_context.file.src,
- .Struct,
- modifiers,
- )
- visit(value_decl.values[0], builder, ast_context)
- case ^Enum_Type:
- write_semantic_node(
- builder,
- value_decl.names[0],
- ast_context.file.src,
- .Enum,
- modifiers,
- )
- visit(value_decl.values[0], builder, ast_context)
- case ^Bit_Set_Type:
- write_semantic_node(
- builder,
- value_decl.names[0],
- ast_context.file.src,
- .Type,
- modifiers,
- )
- visit(value_decl.values[0], builder, ast_context)
- case ^Proc_Group:
- write_semantic_node(
- builder,
- value_decl.names[0],
- ast_context.file.src,
- .Function,
- modifiers,
- )
- for arg in v.args {
- if ident, ok := arg.derived.(^Ident); ok {
- write_semantic_node(
- builder,
- arg,
- ast_context.file.src,
- .Function,
- )
- }
- }
- case ^Proc_Lit:
- write_semantic_node(
- builder,
- value_decl.names[0],
- ast_context.file.src,
- .Function,
- modifiers,
- )
- visit(value_decl.values[0], builder, ast_context)
- case ^Proc_Type:
- write_semantic_node(
- builder,
- value_decl.names[0],
- ast_context.file.src,
- .Type,
- modifiers,
- )
- visit_proc_type(v, builder, ast_context)
- case:
- for name in value_decl.names {
- write_semantic_node(
- builder,
- name,
- ast_context.file.src,
- .Variable,
- modifiers,
- )
- }
+ visit_node(value_decl.type, builder)
- visit(value_decl.values[0], builder, ast_context)
+ for value in value_decl.values {
+ visit_node(value, builder)
}
}
-visit_token_op :: proc(
- builder: ^SemanticTokenBuilder,
- token: tokenizer.Token,
- src: string,
-) {
- if token.text != "in" {
- write_semantic_string(
- builder,
- token.pos,
- token.text,
- src,
- .Operator,
- )
- }
-}
-
-visit_proc_type :: proc(
- node: ^ast.Proc_Type,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
+visit_proc_type :: proc(node: ^ast.Proc_Type, builder: ^SemanticTokenBuilder) {
using ast
if node == nil {
@@ -787,32 +424,23 @@ visit_proc_type :: proc(
for param in node.params.list {
for name in param.names {
if ident, ok := name.derived.(^Ident); ok {
- write_semantic_node(
- builder,
- name,
- ast_context.file.src,
- .Parameter,
- )
+ write_semantic_node(builder, name, .Parameter)
}
}
- visit(param.type, builder, ast_context)
+ visit_node(param.type, builder)
}
}
if node.results != nil {
for result in node.results.list {
- visit(result.names, builder, ast_context)
- visit(result.type, builder, ast_context)
+ visit_nodes(result.names, builder)
+ visit_node(result.type, builder)
}
}
}
-visit_enum_fields :: proc(
- node: ast.Enum_Type,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
+visit_enum_fields :: proc(node: ast.Enum_Type, builder: ^SemanticTokenBuilder) {
using ast
if node.fields == nil {
@@ -821,149 +449,120 @@ visit_enum_fields :: proc(
for field in node.fields {
if ident, ok := field.derived.(^Ident); ok {
- write_semantic_node(
- builder,
- field,
- ast_context.file.src,
- .EnumMember,
- )
+ write_semantic_node(builder, field, .EnumMember)
} else if f, ok := field.derived.(^Field_Value); ok {
if _, ok := f.field.derived.(^Ident); ok {
- write_semantic_node(
- builder,
- f.field,
- ast_context.file.src,
- .EnumMember,
- )
+ write_semantic_node(builder, f.field, .EnumMember)
}
- visit(f.value, builder, ast_context)
+ visit_node(f.value, builder)
}
}
}
-visit_struct_fields :: proc(
- node: ast.Struct_Type,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
- using ast
-
+visit_struct_fields :: proc(node: ast.Struct_Type, builder: ^SemanticTokenBuilder) {
if node.fields == nil {
return
}
for field in node.fields.list {
for name in field.names {
- if ident, ok := name.derived.(^Ident); ok {
- write_semantic_node(
- builder,
- name,
- ast_context.file.src,
- .Property,
- )
+ if ident, ok := name.derived.(^ast.Ident); ok {
+ write_semantic_node(builder, ident, .Property)
}
}
- visit(field.type, builder, ast_context)
+ visit_node(field.type, builder)
}
}
-visit_bit_field_fields :: proc(
- node: ast.Bit_Field_Type,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
+visit_bit_field_fields :: proc(node: ast.Bit_Field_Type, builder: ^SemanticTokenBuilder) {
+ if node.fields == nil {
+ return
+ }
+
for field in node.fields {
if ident, ok := field.name.derived.(^ast.Ident); ok {
- write_semantic_node(
- builder,
- ident,
- ast_context.file.src,
- .Property,
- )
+ write_semantic_node(builder, ident, .Property)
}
- visit(field.type, builder, ast_context)
- visit(field.bit_size, builder, ast_context)
+ visit_node(field.type, builder)
+ visit_node(field.bit_size, builder)
}
}
-visit_selector :: proc(
- selector: ^ast.Selector_Expr,
- builder: ^SemanticTokenBuilder,
- ast_context: ^AstContext,
-) {
- if _, ok := selector.expr.derived.(^ast.Selector_Expr); ok {
- visit_selector(
- cast(^ast.Selector_Expr)selector.expr,
- builder,
- ast_context,
- )
+visit_selector :: proc(selector: ^ast.Selector_Expr, builder: ^SemanticTokenBuilder) {
+ if v, ok := selector.expr.derived.(^ast.Selector_Expr); ok {
+ visit_selector(v, builder)
} else {
- visit(selector.expr, builder, ast_context)
+ visit_node(selector.expr, builder)
builder.selector = true
}
- if symbol_and_node, ok := builder.symbols[cast(uintptr)selector]; ok {
- if symbol_and_node.symbol.type == .Variable {
- write_semantic_node(
- builder,
- selector.field,
- ast_context.file.src,
- .Property,
- )
- } else {
- switch v in symbol_and_node.symbol.value {
- case SymbolPackageValue:
- write_semantic_node(
- builder,
- selector.field,
- ast_context.file.src,
- .Namespace,
- )
- case SymbolStructValue,
- SymbolBitFieldValue:
- write_semantic_node(
- builder,
- selector.field,
- ast_context.file.src,
- .Struct,
- )
- case SymbolEnumValue,
- SymbolUnionValue:
- write_semantic_node(
- builder,
- selector.field,
- ast_context.file.src,
- .Enum,
- )
- case SymbolProcedureValue,
- SymbolProcedureGroupValue,
- SymbolAggregateValue:
- write_semantic_node(
- builder,
- selector.field,
- ast_context.file.src,
- .Function,
- )
- case SymbolMatrixValue,
- SymbolBitSetValue,
- SymbolDynamicArrayValue,
- SymbolFixedArrayValue,
- SymbolSliceValue,
- SymbolMapValue,
- SymbolMultiPointer:
- write_semantic_node(
- builder,
- selector.field,
- ast_context.file.src,
- .Type,
- )
- case SymbolBasicValue, SymbolUntypedValue:
- // handled by static syntax analysis
- case SymbolGenericValue:
- // unused
- }
+ visit_ident(selector.field, {}, builder)
+}
+
+visit_ident :: proc(
+ ident: ^ast.Ident,
+ modifiers: SemanticTokenModifiers,
+ builder: ^SemanticTokenBuilder,
+) {
+ using ast
+
+ symbol_and_node, in_symbols := builder.symbols[cast(uintptr)ident]
+ if !in_symbols {
+ return
+ }
+ symbol := symbol_and_node.symbol
+
+ modifiers := modifiers
+ if symbol.type != .Variable {
+ modifiers += {.ReadOnly}
+ }
+
+ if .Distinct in symbol.flags && symbol.type == .Constant {
+ write_semantic_node(builder, ident, .Type)
+ return
+ }
+
+ #partial switch symbol.type {
+ case .Variable, .Constant:
+ #partial switch _ in symbol.value {
+ case SymbolProcedureValue:
+ write_semantic_node(builder, ident, .Function, modifiers)
+ case:
+ write_semantic_node(builder, ident, .Variable, modifiers)
}
+ case .Type_Function:
+ write_semantic_node(builder, ident, .Type, modifiers)
+ }
+
+ switch v in symbol.value {
+ case SymbolPackageValue:
+ write_semantic_node(builder, ident, .Namespace, modifiers)
+ case SymbolStructValue,
+ SymbolBitFieldValue:
+ write_semantic_node(builder, ident, .Struct, modifiers)
+ case SymbolEnumValue,
+ SymbolUnionValue:
+ write_semantic_node(builder, ident, .Enum, modifiers)
+ case SymbolProcedureValue,
+ SymbolProcedureGroupValue,
+ SymbolAggregateValue:
+ write_semantic_node(builder, ident, .Function, modifiers)
+ case SymbolMatrixValue,
+ SymbolBitSetValue,
+ SymbolDynamicArrayValue,
+ SymbolFixedArrayValue,
+ SymbolSliceValue,
+ SymbolMapValue,
+ SymbolMultiPointer:
+ write_semantic_node(builder, ident, .Type, modifiers)
+ case SymbolBasicValue, SymbolUntypedValue:
+ // handled by static syntax analysis
+ case SymbolGenericValue:
+ // unused
+ case:
+ // log.errorf("Unexpected symbol value: %v", symbol.value);
+ // panic(fmt.tprintf("Unexpected symbol value: %v", symbol.value));
}
}