diff options
| author | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-09-07 21:24:33 -0400 |
|---|---|---|
| committer | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-09-07 21:38:30 -0400 |
| commit | 19ee061feef6f74b54a4ca5e36a8e3711907935b (patch) | |
| tree | 0f9649a1bc288959f14da6712cff65274fc63d06 /src | |
| parent | 7d334f6c9fff565b5d51c30e13db810f466e6241 (diff) | |
Distinguish between variables and types when parsing globals
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/analysis.odin | 13 | ||||
| -rw-r--r-- | src/server/ast.odin | 47 | ||||
| -rw-r--r-- | src/server/collector.odin | 10 | ||||
| -rw-r--r-- | src/server/semantic_tokens.odin | 44 | ||||
| -rw-r--r-- | src/server/symbol.odin | 3 |
5 files changed, 61 insertions, 56 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin index ac3680c..22324f4 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -1733,7 +1733,7 @@ resolve_global_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, glo } if ok = internal_resolve_type_expression(ast_context, v.expr, &return_symbol); ok { - return_types := get_proc_return_types(ast_context, return_symbol, v, global.mutable) + return_types := get_proc_return_types(ast_context, return_symbol, v, .Mutable in global.flags) if len(return_types) > 0 { ok = internal_resolve_type_expression(ast_context, return_types[0], &return_symbol) } @@ -1799,7 +1799,7 @@ resolve_global_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, glo case ^ast.Basic_Lit: return_symbol, ok = resolve_basic_lit(ast_context, v^) return_symbol.name = node.name - return_symbol.type = global.mutable ? .Variable : .Constant + return_symbol.type = .Mutable in global.flags ? .Variable : .Constant case: ok = internal_resolve_type_expression(ast_context, global.expr, &return_symbol) } @@ -1809,10 +1809,17 @@ resolve_global_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, glo return_symbol.flags |= {.Distinct} } - if global.mutable { + if .Mutable in global.flags { return_symbol.type = .Variable } + if .Variable in global.flags { + return_symbol.flags |= {.Variable} + } + if .Mutable in global.flags { + return_symbol.flags |= {.Mutable} + } + if global.docs != nil { return_symbol.doc = get_doc(global.name_expr, global.docs, ast_context.allocator) } diff --git a/src/server/ast.odin b/src/server/ast.odin index e658123..2580338 100644 --- a/src/server/ast.odin +++ b/src/server/ast.odin @@ -82,11 +82,16 @@ are_keyword_aliases :: proc(a, b: string) -> bool { return false } +GlobalFlags :: enum { + Mutable, // or constant + Variable, // or type +} + GlobalExpr :: struct { name: string, name_expr: ^ast.Expr, expr: ^ast.Expr, - mutable: bool, + flags: bit_set[GlobalFlags], docs: ^ast.Comment_Group, comment: ^ast.Comment_Group, attributes: []^ast.Attribute, @@ -353,6 +358,17 @@ merge_attributes :: proc(attrs: []^ast.Attribute, foreign_attrs: []^ast.Attribut return new_attrs[:] } +// TODO: it seems the global symbols don't distinguish between a type decl and +// a const variable declaration, so we do a quick check here to distinguish the cases. +is_variable_declaration :: proc(expr: ^ast.Expr) -> bool { + #partial switch v in expr.derived { + case ^ast.Comp_Lit, ^ast.Basic_Lit, ^ast.Type_Cast, ^ast.Call_Expr: + return true + case: + return false + } +} + collect_value_decl :: proc( exprs: ^[dynamic]GlobalExpr, file: ast.File, @@ -370,13 +386,16 @@ collect_value_decl :: proc( attributes := merge_attributes(value_decl.attributes[:], foreign_attrs) global_expr := GlobalExpr { - mutable = value_decl.is_mutable, docs = value_decl.docs, comment = comment, attributes = attributes, private = file_tags.private, } + if value_decl.is_mutable { + global_expr.flags += {.Mutable} + } + for attribute in attributes { for elem in attribute.elems { ident, value, ok := unwrap_attr_elem(elem) @@ -414,6 +433,11 @@ collect_value_decl :: proc( global_expr.name = get_ast_node_string(name, file.src) global_expr.name_expr = name + if len(value_decl.values) > i { + if is_variable_declaration(value_decl.values[i]) { + global_expr.flags += {.Variable} + } + } if value_decl.type != nil { global_expr.expr = value_decl.type append(exprs, global_expr) @@ -477,13 +501,7 @@ collect_when_body :: proc( if foreign_decl.body != nil { if foreign_block, ok := foreign_decl.body.derived.(^ast.Block_Stmt); ok { for foreign_stmt in foreign_block.stmts { - collect_value_decl( - exprs, - file, - file_tags, - foreign_stmt, - foreign_decl.attributes[:], - ) + collect_value_decl(exprs, file, file_tags, foreign_stmt, foreign_decl.attributes[:]) } } } @@ -732,8 +750,8 @@ free_ast_node :: proc(node: ^ast.Node, allocator: mem.Allocator) { free_ast(n.names, allocator) free_ast(n.type, allocator) free_ast(n.default_value, allocator) - free_ast_comment(n.docs, allocator); - free_ast_comment(n.comment, allocator); + free_ast_comment(n.docs, allocator) + free_ast_comment(n.comment, allocator) case ^Field_List: free_ast(n.list, allocator) case ^Typeid_Type: @@ -1306,7 +1324,12 @@ construct_struct_field_docs :: proc(file: ast.File, v: ^ast.Struct_Type, allocat field.comment.list = list[:1] } if len(list) > 1 { - next_field.docs = new_type(ast.Comment_Group, list[1].pos, parser.end_pos(list[len(list) - 2]), allocator) + next_field.docs = new_type( + ast.Comment_Group, + list[1].pos, + parser.end_pos(list[len(list) - 2]), + allocator, + ) next_field.docs.list = list[1:] } else { next_field.docs = nil diff --git a/src/server/collector.odin b/src/server/collector.odin index 4588a39..a702546 100644 --- a/src/server/collector.odin +++ b/src/server/collector.odin @@ -663,7 +663,7 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri token = v^ symbol.value = collect_generic(collection, col_expr, package_map, uri) - if expr.mutable { + if .Mutable in expr.flags { token_type = .Variable } else { token_type = .Unresolved @@ -671,7 +671,7 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri case ^ast.Comp_Lit: generic := collect_generic(collection, col_expr, package_map, uri) - if expr.mutable { + if .Mutable in expr.flags { token_type = .Variable } else { token_type = .Unresolved @@ -685,7 +685,7 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri // default symbol.value = collect_generic(collection, col_expr, package_map, uri) - if expr.mutable { + if .Mutable in expr.flags { token_type = .Variable } else { token_type = .Unresolved @@ -734,6 +734,10 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri symbol.flags |= {.PrivatePackage} } + if .Variable in expr.flags { + symbol.flags |= {.Variable} + } + pkg: ^SymbolPackage ok: bool diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin index 7210ccf..703a0cb 100644 --- a/src/server/semantic_tokens.odin +++ b/src/server/semantic_tokens.odin @@ -390,44 +390,14 @@ visit_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder) { } } -// TODO: it seems the global symbols don't distinguish between a type decl and -// a const variable declaration, so we do a quick check here to distinguish the cases. -is_variable_declaration :: proc(expr: ^ast.Expr) -> bool { - #partial switch v in expr.derived { - case ^ast.Comp_Lit, ^ast.Basic_Lit, ^ast.Type_Cast, ^ast.Call_Expr: - return true - case: - return false - } -} - visit_value_decl :: proc(value_decl: ast.Value_Decl, builder: ^SemanticTokenBuilder) { using ast modifiers: SemanticTokenModifiers = value_decl.is_mutable ? {} : {.ReadOnly} - // Check if we are a comp lit or a type declaration - - // a, b, c :: 1, 2, 3 - // a := 1 - if len(value_decl.values) == len(value_decl.names) { - for name, i in value_decl.names { - ident := name.derived.(^Ident) or_continue - is_var_decl := is_variable_declaration(value_decl.values[i]) - visit_ident(ident, ident, modifiers, builder, is_var_decl) - } - } else if len(value_decl.values) > 0 { - // a, b: int - is_var_decl := is_variable_declaration(value_decl.values[0]) - for name in value_decl.names { - ident := name.derived.(^Ident) or_continue - visit_ident(ident, ident, modifiers, builder, is_var_decl) - } - } else { - for name in value_decl.names { - ident := name.derived.(^Ident) or_continue - visit_ident(ident, ident, modifiers, builder) - } + for name in value_decl.names { + ident := name.derived.(^Ident) or_continue + visit_ident(ident, ident, modifiers, builder) } visit_node(value_decl.type, builder) @@ -559,7 +529,6 @@ visit_ident :: proc( symbol_ptr: rawptr, modifiers: SemanticTokenModifiers, builder: ^SemanticTokenBuilder, - is_variable_decl := false, ) { using ast @@ -571,14 +540,15 @@ visit_ident :: proc( modifiers := modifiers - if symbol.type != .Variable { + if .Mutable not_in symbol.flags { modifiers += {.ReadOnly} } - if is_variable_decl { + if .Variable in symbol.flags { write_semantic_node(builder, ident, .Variable, modifiers) return } + /* variable idents */ #partial switch symbol.type { case .Variable, .Constant, .Function: @@ -612,7 +582,7 @@ visit_ident :: proc( SymbolMapValue, SymbolMultiPointerValue, SymbolBasicValue, - SymbolPolyTypeValue: + SymbolPolyTypeValue: write_semantic_node(builder, ident, .Type, modifiers) case SymbolUntypedValue: // handled by static syntax highlighting diff --git a/src/server/symbol.odin b/src/server/symbol.odin index 2090f3b..9e220c5 100644 --- a/src/server/symbol.odin +++ b/src/server/symbol.odin @@ -194,7 +194,8 @@ SymbolFlag :: enum { PrivateFile, PrivatePackage, Anonymous, //Usually applied to structs that are defined inline inside another struct - Variable, //Symbols that are variable, this means their value decl was mutable + Variable, // or type + Mutable, // or constant Local, ObjC, ObjCIsClassMethod, // should be set true only when ObjC is enabled |