diff options
| author | Daniel Gavin <danielgavin5@hotmail.com> | 2022-01-17 12:54:17 +0100 |
|---|---|---|
| committer | Daniel Gavin <danielgavin5@hotmail.com> | 2022-01-17 12:54:17 +0100 |
| commit | 64e56f1610a568331b19ab713ea033030f0eac2d (patch) | |
| tree | 45674a85f8c4f29cc8c83d6af9715687b963a9fe /src | |
| parent | 273de152aee21ed4855bf4b6fdbd08d494995863 (diff) | |
work on the new semantic tokens.
Diffstat (limited to 'src')
| -rw-r--r-- | src/analysis/analysis.odin | 83 | ||||
| -rw-r--r-- | src/server/requests.odin | 12 | ||||
| -rw-r--r-- | src/server/semantic_tokens.odin | 374 |
3 files changed, 410 insertions, 59 deletions
diff --git a/src/analysis/analysis.odin b/src/analysis/analysis.odin index cdf4f98..5d50e50 100644 --- a/src/analysis/analysis.odin +++ b/src/analysis/analysis.odin @@ -837,13 +837,20 @@ lookup_symbol_cache :: proc(ast_context: ^AstContext, node: ast.Node) -> (index. return {}, false; } - if cached := &ast_context.symbol_cache[node.pos.offset]; cached != nil { + if cached := &ast_context.symbol_cache[node.end.offset]; cached != nil { symbol := cast(^index.Symbol)cached^; return symbol^, true; } return {}, false; } +store_symbol_cache :: proc(ast_context: ^AstContext, data: rawptr, offset: int) { + if ast_context.document_package != ast_context.current_package { + return; + } + ast_context.symbol_cache[offset] = cast(rawptr)data; +} + resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (index.Symbol, bool) { if symbol, ok := lookup_symbol_cache(ast_context, node^); ok { return symbol, true; @@ -853,7 +860,7 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i if symbol, ok := internal_resolve_type_expression(ast_context, node); ok { cached_symbol := index.new_clone_symbol(symbol); - ast_context.symbol_cache[node.end.offset] = cast(rawptr)cached_symbol; + store_symbol_cache(ast_context, cached_symbol, node.end.offset); return symbol, true; } @@ -1143,7 +1150,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i if symbol, ok := internal_resolve_type_identifier(ast_context, node); ok { cached_symbol := index.new_clone_symbol(symbol); - ast_context.symbol_cache[node.end.offset] = cast(rawptr)cached_symbol; + store_symbol_cache(ast_context, cached_symbol, node.end.offset); return symbol, true; } @@ -1536,7 +1543,6 @@ resolve_unresolved_symbol :: proc(ast_context: ^AstContext, symbol: ^index.Symbo } resolve_location_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (index.Symbol, bool) { - symbol: index.Symbol; if local := get_local(ast_context, node.pos.offset, node.name); local != nil { @@ -1563,7 +1569,6 @@ resolve_location_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) - } resolve_first_symbol_from_binary_expression :: proc(ast_context: ^AstContext, binary: ^ast.Binary_Expr) -> (index.Symbol, bool) { - //Fairly simple function to find the earliest identifier symbol in binary expression. if binary.left != nil { @@ -1595,7 +1600,6 @@ resolve_first_symbol_from_binary_expression :: proc(ast_context: ^AstContext, bi } find_position_in_call_param :: proc(ast_context: ^AstContext, call: ast.Call_Expr) -> (int, bool) { - if call.args == nil { return 0, false; } @@ -1646,7 +1650,6 @@ get_package_from_node :: proc(node: ast.Node) -> string { } get_using_packages :: proc(ast_context: ^AstContext) -> []string { - usings := make([]string, len(ast_context.usings), context.temp_allocator); if len(ast_context.usings) == 0 { @@ -1668,7 +1671,6 @@ get_using_packages :: proc(ast_context: ^AstContext) -> []string { } make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, v: ast.Proc_Type, name: string) -> index.Symbol { - symbol := index.Symbol { range = common.get_token_range(n^, ast_context.file.src), type = .Function, @@ -1706,7 +1708,6 @@ make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, v } make_symbol_array_from_ast :: proc(ast_context: ^AstContext, v: ast.Array_Type) -> index.Symbol { - symbol := index.Symbol { range = common.get_token_range(v.node, ast_context.file.src), type = .Variable, @@ -1728,7 +1729,6 @@ make_symbol_array_from_ast :: proc(ast_context: ^AstContext, v: ast.Array_Type) } make_symbol_dynamic_array_from_ast :: proc(ast_context: ^AstContext, v: ast.Dynamic_Array_Type) -> index.Symbol { - symbol := index.Symbol { range = common.get_token_range(v.node, ast_context.file.src), type = .Variable, @@ -1743,7 +1743,6 @@ make_symbol_dynamic_array_from_ast :: proc(ast_context: ^AstContext, v: ast.Dyna } make_symbol_map_from_ast :: proc(ast_context: ^AstContext, v: ast.Map_Type) -> index.Symbol { - symbol := index.Symbol { range = common.get_token_range(v.node, ast_context.file.src), type = .Variable, @@ -1759,7 +1758,6 @@ make_symbol_map_from_ast :: proc(ast_context: ^AstContext, v: ast.Map_Type) -> i } make_symbol_basic_type_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, v: ^ast.Ident) -> index.Symbol { - symbol := index.Symbol { range = common.get_token_range(n^, ast_context.file.src), type = .Variable, @@ -1774,7 +1772,6 @@ make_symbol_basic_type_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, } make_symbol_union_from_ast :: proc(ast_context: ^AstContext, v: ast.Union_Type, ident: string, inlined := false) -> index.Symbol { - symbol := index.Symbol { range = common.get_token_range(v, ast_context.file.src), type = .Union, @@ -1848,7 +1845,6 @@ make_symbol_enum_from_ast :: proc(ast_context: ^AstContext, v: ast.Enum_Type, id } make_symbol_bitset_from_ast :: proc(ast_context: ^AstContext, v: ast.Bit_Set_Type, ident: string, inlined := false) -> index.Symbol { - symbol := index.Symbol { range = common.get_token_range(v, ast_context.file.src), type = .Enum, @@ -1869,7 +1865,6 @@ make_symbol_bitset_from_ast :: proc(ast_context: ^AstContext, v: ast.Bit_Set_Typ } make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type, ident: string, inlined := false) -> index.Symbol { - symbol := index.Symbol { range = common.get_token_range(v, ast_context.file.src), type = .Struct, @@ -2038,7 +2033,6 @@ resolve_poly_struct :: proc(ast_context: ^AstContext, poly_params: ^ast.Field_Li } get_globals :: proc(file: ast.File, ast_context: ^AstContext) { - ast_context.variables["context"] = true; exprs := common.collect_globals(file); @@ -2050,7 +2044,6 @@ get_globals :: proc(file: ast.File, ast_context: ^AstContext) { } get_generic_assignment :: proc(file: ast.File, value: ^ast.Expr, ast_context: ^AstContext, results: ^[dynamic]^ast.Expr) { - using ast; ast_context.use_locals = true; @@ -2067,7 +2060,6 @@ get_generic_assignment :: proc(file: ast.File, value: ^ast.Expr, ast_context: ^A } } } - case Comp_Lit: if v.type != nil { append(results, v.type); @@ -2400,7 +2392,7 @@ get_locals_type_switch_stmt :: proc(file: ast.File, stmt: ast.Type_Switch_Stmt, } } -get_locals_proc_param_and_results :: proc(file: ast.File, function: ^ast.Node, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { +get_locals_proc_param_and_results :: proc(file: ast.File, function: ast.Proc_Lit, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { proc_lit, ok := function.derived.(ast.Proc_Lit); if !ok || proc_lit.body == nil { @@ -2458,7 +2450,7 @@ get_locals :: proc(file: ast.File, function: ^ast.Node, ast_context: ^AstContext return; } - get_locals_proc_param_and_results(file, function, ast_context, document_position); + get_locals_proc_param_and_results(file, proc_lit, ast_context, document_position); block: ast.Block_Stmt; block, ok = proc_lit.body.derived.(ast.Block_Stmt); @@ -2480,26 +2472,22 @@ clear_locals :: proc(ast_context: ^AstContext) { clear(&ast_context.usings); } -resolve_entire_file :: proc(document: ^common.Document, allocator := context.allocator) -> []index.Symbol { - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache); - - get_globals(document.ast, &ast_context); +resolve_entire_file :: proc(document: ^common.Document, ast_context: ^AstContext, allocator := context.allocator) -> []index.Symbol { + get_globals(document.ast, ast_context); ast_context.current_package = ast_context.document_package; symbols := make([dynamic]index.Symbol, allocator); - for decl in document.ast.decls { - switch v in decl.derived { + for k, v in ast_context.globals { + switch n in v.expr.derived { case ast.Proc_Lit: - position_context: DocumentPositionContext; - position_context.position = v.end.offset; - //get_locals_proc_param_and_results - //get_locals_stmt() - resolve_entire_procedure(&ast_context, v, &symbols, allocator); + resolve_entire_procedure(ast_context, n, &symbols, allocator); + clear_local_group(ast_context, 0); + add_local_group(ast_context, 0); } } - + return symbols[:]; } @@ -2528,6 +2516,8 @@ resolve_entire_procedure :: proc(ast_context: ^AstContext, procedure: ast.Proc_L } data := cast(^Visit_Data)visitor.data; ast_context := data.ast_context; + ast_context.use_locals = true; + ast_context.use_globals = true; //It's somewhat silly to check the scope everytime, but the alternative is to implement my own walker function. if len(data.scopes) > 0 { @@ -2554,8 +2544,19 @@ resolve_entire_procedure :: proc(ast_context: ^AstContext, procedure: ast.Proc_L scope.offset = node.end.offset; data.id_counter += 1; ast_context.local_id = scope.id; + append(&data.scopes, scope); add_local_group(ast_context, scope.id); + + position_context: DocumentPositionContext; + position_context.position = node.end.offset; + get_locals_stmt(ast_context.file, cast(^ast.Stmt)node, ast_context, &position_context); + } + + + switch v in &node.derived { + case ast.If_Stmt: + case ast.For_Stmt: //get_locals_stmt(ast_context.file, v, ast_context, ) case ast.Ident: if symbol, ok := resolve_type_identifier(ast_context, v); ok { @@ -2575,12 +2576,20 @@ resolve_entire_procedure :: proc(ast_context: ^AstContext, procedure: ast.Proc_L visit = visit, } - ast.walk(&visitor, procedure.body); - - if procedure.type != nil { - ast.walk(&visitor, procedure.type.params); - ast.walk(&visitor, procedure.type.results); + if procedure.body == nil { + return; } + + type_position_context: DocumentPositionContext; + type_position_context.position = procedure.end.offset; + get_locals_proc_param_and_results(ast_context.file, procedure, ast_context, &type_position_context); + + body_position_context: DocumentPositionContext; + body_position_context.position = procedure.body.end.offset; + + get_locals_stmt(ast_context.file, cast(^ast.Stmt)procedure.body, ast_context, &body_position_context); + + ast.walk(&visitor, procedure.body); } concatenate_symbol_information :: proc { diff --git a/src/server/requests.odin b/src/server/requests.odin index 8d965c7..c4bd7b9 100644 --- a/src/server/requests.odin +++ b/src/server/requests.odin @@ -589,7 +589,6 @@ request_initialized :: proc (task: ^common.Task) { } request_shutdown :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -607,7 +606,6 @@ request_shutdown :: proc (task: ^common.Task) { } request_definition :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -648,7 +646,6 @@ request_definition :: proc (task: ^common.Task) { } request_completion :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -692,7 +689,6 @@ request_completion :: proc (task: ^common.Task) { } request_signature_help :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -733,7 +729,6 @@ request_signature_help :: proc (task: ^common.Task) { } request_format_document :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -786,7 +781,6 @@ notification_exit :: proc (task: ^common.Task) { } notification_did_open :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -818,7 +812,6 @@ notification_did_open :: proc (task: ^common.Task) { } notification_did_change :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -846,7 +839,6 @@ notification_did_change :: proc (task: ^common.Task) { } notification_did_close :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -952,7 +944,6 @@ notification_did_save :: proc (task: ^common.Task) { } request_semantic_token_full :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -1001,7 +992,6 @@ request_semantic_token_full :: proc (task: ^common.Task) { } request_semantic_token_range :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -1040,7 +1030,6 @@ request_semantic_token_range :: proc (task: ^common.Task) { } request_document_symbols :: proc (task: ^common.Task) { - info := get_request_info(task); using info; @@ -1075,7 +1064,6 @@ request_document_symbols :: proc (task: ^common.Task) { } request_hover :: proc (task: ^common.Task) { - info := get_request_info(task); using info; diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin index f7d01dd..095bb91 100644 --- a/src/server/semantic_tokens.odin +++ b/src/server/semantic_tokens.odin @@ -81,7 +81,7 @@ SemanticTokenBuilder :: struct { make_token_builder :: proc(allocator := context.temp_allocator) -> SemanticTokenBuilder { return { - tokens = make([dynamic]u32, context.temp_allocator), + tokens = make([dynamic]u32, 1000, context.temp_allocator), }; } @@ -100,11 +100,15 @@ get_semantic_tokens :: proc(document: ^common.Document, range: common.Range) -> write_semantic_token(&builder, document.ast.pkg_token, document.ast.src, .Keyword, .None); } - resolve_entire_file(document, context.temp_allocator); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache); + + //resolve_entire_file(document, &ast_context, context.temp_allocator); + + ast_context.current_package = ast_context.document_package; for decl in document.ast.decls { if range.start.line <= decl.pos.line && decl.end.line <= range.end.line { - + visit(decl, &builder, &ast_context); } } @@ -113,27 +117,377 @@ get_semantic_tokens :: proc(document: ^common.Document, range: common.Range) -> write_semantic_node :: proc(builder: ^SemanticTokenBuilder, node: ^ast.Node, src: string, type: SemanticTokenTypes, modifier: SemanticTokenModifiers) { position := common.get_relative_token_position(node.pos.offset, transmute([]u8)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)type, 0); - builder.current_start = node.pos.offset; } write_semantic_token :: proc(builder: ^SemanticTokenBuilder, token: tokenizer.Token, src: string, type: SemanticTokenTypes, modifier: 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, 0); - builder.current_start = token.pos.offset; } write_semantic_string :: proc(builder: ^SemanticTokenBuilder, pos: tokenizer.Pos, name: string, src: string, type: SemanticTokenTypes, modifier: 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, 0); - 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: ^analysis.AstContext) { + for elem, i in array { + visit(elem, builder, ast_context); + } +} + +visit_dynamic_array :: proc(array: $A/[dynamic]^$T, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { + for elem, i in array { + visit(elem, builder, ast_context); + } +} + +visit_stmt :: proc(node: ^ast.Stmt, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { + visit_node(node, builder, ast_context); +} + +visit_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { + using ast; + + if node == nil { + return; + } + + switch n in node.derived { + case Ellipsis: + write_semantic_string(builder, node.pos, "..", ast_context.file.src, .Operator, .None); + visit(n.expr, builder, ast_context); + case Ident: + if true { + write_semantic_node(builder, node, ast_context.file.src, .Variable, .None); + return; + } + if symbol, ok := analysis.lookup_symbol_cache(ast_context, n); ok { + if symbol.type == .Variable { + write_semantic_node(builder, node, ast_context.file.src, .Variable, .None); + } + + #partial switch v in symbol.value { + case index.SymbolPackageValue: + write_semantic_node(builder, node, ast_context.file.src, .Namespace, .None); + case index.SymbolStructValue: + write_semantic_node(builder, node, ast_context.file.src, .Struct, .None); + case index.SymbolEnumValue: + write_semantic_node(builder, node, ast_context.file.src, .Enum, .None); + case index.SymbolUnionValue: + write_semantic_node(builder, node, ast_context.file.src, .Enum, .None); + case index.SymbolProcedureValue: + write_semantic_node(builder, node, ast_context.file.src, .Function, .None); + case index.SymbolProcedureGroupValue: + write_semantic_node(builder, node, ast_context.file.src, .Function, .None); + } + } + case Selector_Expr: + visit_selector(cast(^Selector_Expr)node, builder, ast_context); + case Pointer_Type: + write_semantic_string(builder, node.pos, "^", ast_context.file.src, .Operator, .None); + visit(n.elem, builder, ast_context); + case Value_Decl: + visit_value_decl(n, builder, ast_context); + case Block_Stmt: + visit(n.stmts, builder, ast_context); + case Expr_Stmt: + visit(n.expr, builder, ast_context); + case Range_Stmt: + write_semantic_string(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None); + + for val in n.vals { + if ident, ok := val.derived.(Ident); ok { + write_semantic_node(builder, val, ast_context.file.src, .Variable, .None); + } + } + + write_semantic_string(builder, n.in_pos, "in", ast_context.file.src, .Keyword, .None); + visit(n.expr, builder, ast_context); + visit(n.body, builder, ast_context); + case If_Stmt: + write_semantic_string(builder, n.if_pos, "if", ast_context.file.src, .Keyword, .None); + visit(n.init, builder, ast_context); + visit(n.cond, builder, ast_context); + visit(n.body, builder, ast_context); + if n.else_stmt != nil { + write_semantic_string(builder, n.else_pos, "else", ast_context.file.src, .Keyword, .None); + visit(n.else_stmt, builder, ast_context); + } + case For_Stmt: + write_semantic_string(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None); + visit(n.init, builder, ast_context); + visit(n.cond, builder, ast_context); + visit(n.post, builder, ast_context); + visit(n.body, builder, ast_context); + case Switch_Stmt: + write_semantic_string(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None); + visit(n.init, builder, ast_context); + visit(n.cond, builder, ast_context); + visit(n.body, builder, ast_context); + case Type_Switch_Stmt: + write_semantic_string(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None); + visit(n.tag, builder, ast_context); + visit(n.expr, builder, ast_context); + visit(n.body, builder, ast_context); + 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, .None); + } else { + visit(l, builder, ast_context); + } + } + + visit_token_op(builder, n.op, ast_context.file.src); + visit(n.rhs, builder, ast_context); + case Case_Clause: + write_semantic_string(builder, n.case_pos, "case", ast_context.file.src, .Keyword, .None); + visit(n.list, builder, ast_context); + visit(n.body, builder, ast_context); + case Call_Expr: + if ident, ok := n.expr.derived.(Ident); ok { + write_semantic_node(builder, n.expr, ast_context.file.src, .Function, .None); + } else { + visit(n.expr, builder, ast_context); + } + visit(n.args, builder, ast_context); + case Implicit_Selector_Expr: + write_semantic_node(builder, n.field, ast_context.file.src, .Enum, .None); + case Array_Type: + visit(n.elem, builder, ast_context); + 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); + case Comp_Lit: + visit(n.type, builder, ast_context); + visit(n.elems, builder, ast_context); + case Struct_Type: + write_semantic_string(builder, n.pos, "struct", ast_context.file.src, .Keyword, .None); + visit_struct_fields(n, builder, ast_context); + case Type_Assertion: + visit(n.expr, builder, ast_context); + visit(n.type, builder, ast_context); + case Type_Cast: + write_semantic_string(builder, n.pos, "cast", ast_context.file.src, .Keyword, .None); + visit(n.type, builder, ast_context); + visit(n.expr, builder, ast_context); + case Paren_Expr: + visit(n.expr, builder, ast_context); + case Deref_Expr: + visit(n.expr, builder, ast_context); + case Return_Stmt: + write_semantic_string(builder, n.pos, "return", ast_context.file.src, .Keyword, .None); + visit(n.results, builder, ast_context); + case Dynamic_Array_Type: + write_semantic_string(builder, n.dynamic_pos, "dynamic", ast_context.file.src, .Keyword, .None); + visit(n.elem, builder, ast_context); + case Field_Value: + if ident, ok := n.field.derived.(Ident); ok { + write_semantic_node(builder, n.field, ast_context.file.src, .Property, .None); + } + + visit(n.value, builder, ast_context); + 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); + case Unary_Expr: + visit(n.expr, builder, ast_context); + case Implicit: + case Slice_Expr: + visit(n.expr, builder, ast_context); + case Using_Stmt: + write_semantic_string(builder, n.pos, "using", ast_context.file.src, .Keyword, .None); + visit(n.list, builder, ast_context); + case Map_Type: + write_semantic_string(builder, n.tok_pos, "map", ast_context.file.src, .Keyword, .None); + visit(n.key, builder, ast_context); + visit(n.value, builder, ast_context); + case Defer_Stmt: + write_semantic_string(builder, n.pos, "defer", ast_context.file.src, .Keyword, .None); + visit(n.stmt, builder, ast_context); + case Import_Decl: + write_semantic_token(builder, n.import_tok, ast_context.file.src, .Keyword, .None); + + if n.name.text != "" { + write_semantic_token(builder, n.name, ast_context.file.src, .Namespace, .None); + } + + write_semantic_token(builder, n.relpath, ast_context.file.src, .String, .None); + case: + log.warnf("unhandled write node %v", n); + } +} + +visit_basic_lit :: proc(basic_lit: ast.Basic_Lit, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { + using analysis; + + if symbol, ok := resolve_basic_lit(ast_context, basic_lit); ok { + + if generic, ok := symbol.value.(index.SymbolGenericValue); ok { + + ident := generic.expr.derived.(ast.Ident); + + if ident.name == "string" { + write_semantic_node(builder, generic.expr, ast_context.file.src, .String, .None); + } else if ident.name == "int" { + write_semantic_node(builder, generic.expr, ast_context.file.src, .Number, .None); + } else { + } + } + } +} + +visit_value_decl :: proc(value_decl: ast.Value_Decl, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { + using ast; + + if value_decl.type != nil { + for name in value_decl.names { + write_semantic_node(builder, name, ast_context.file.src, .Variable, .None); + } + + visit(value_decl.type, builder, ast_context); + + return; + } + + if len(value_decl.values) == 1 { + switch v in value_decl.values[0].derived { + case Struct_Type: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Struct, .None); + write_semantic_string(builder, v.pos, "struct", ast_context.file.src, .Keyword, .None); + visit_struct_fields(v, builder, ast_context); + case Enum_Type: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Enum, .None); + write_semantic_string(builder, v.pos, "enum", ast_context.file.src, .Keyword, .None); + visit_enum_fields(v, builder, ast_context); + case Proc_Group: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Function, .None); + write_semantic_string(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None); + for arg in v.args { + if ident, ok := arg.derived.(Ident); ok { + write_semantic_node(builder, arg, ast_context.file.src, .Function, .None); + } + } + case Proc_Lit: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Function, .None); + write_semantic_string(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None); + visit_proc_type(v.type, builder, ast_context); + + visit(v.body, builder, ast_context); + case: + for name in value_decl.names { + write_semantic_node(builder, name, ast_context.file.src, .Variable, .None); + } + + visit(value_decl.values[0], builder, ast_context); + } + } else { + for name in value_decl.names { + write_semantic_node(builder, name, ast_context.file.src, .Variable, .None); + } + + for value in value_decl.values { + visit(value, builder, ast_context); + } + } +} + +visit_token_op :: proc(builder: ^SemanticTokenBuilder, token: tokenizer.Token, src: string) { + if token.text == "in" { + write_semantic_string(builder, token.pos, token.text, src, .Keyword, .None); + } else { + write_semantic_string(builder, token.pos, token.text, src, .Operator, .None); + } +} + +visit_proc_type :: proc(node: ^ast.Proc_Type, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { + using ast; + + if node == nil { + return; + } + + if node.params != nil { + 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, .None); + } + } + + visit(param.type, builder, ast_context); + } + } + + if node.results != nil { + for result in node.results.list { + for name in result.names { + if ident, ok := name.derived.(Ident); ok { + //write_semantic_node(builder, name, ast_context.file.src, .Parameter, .None); + } + } + + visit(result.type, builder, ast_context); + } + } +} + +visit_enum_fields :: proc(node: ast.Enum_Type, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { + using ast; + + if node.fields == nil { + return; + } + + for field in node.fields { + + if ident, ok := field.derived.(Ident); ok { + write_semantic_node(builder, field, ast_context.file.src, .EnumMember, .None); + } + else if f, ok := field.derived.(Field_Value); ok { + if ident, ok := f.field.derived.(Ident); ok { + write_semantic_node(builder, f.field, ast_context.file.src, .EnumMember, .None); + } + visit(f.value, builder, ast_context); + } + } +} + +visit_struct_fields :: proc(node: ast.Struct_Type, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { + using ast; + + 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, .None); + } + } + + visit(field.type, builder, ast_context); + } +} + +visit_selector :: proc(selector: ^ast.Selector_Expr, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { + using analysis; + using ast; +}
\ No newline at end of file |