diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/analysis.odin | 121 | ||||
| -rw-r--r-- | src/server/requests.odin | 42 | ||||
| -rw-r--r-- | src/server/semantic_tokens.odin | 304 |
3 files changed, 378 insertions, 89 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 248849a..7cd5c35 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -40,12 +40,14 @@ AstContext :: struct { locals: map [string] ^ast.Expr, //locals all the way to the document position globals: map [string] ^ast.Expr, variables: map [string] bool, + parameters: map [string] bool, usings: [dynamic] string, file: ast.File, allocator: mem.Allocator, imports: [] Package, //imports for the current document current_package: string, document_package: string, + use_package: bool, use_globals: bool, use_locals: bool, call: ^ast.Expr, //used to determene the types for generics and the correct function for overloaded functions @@ -58,6 +60,7 @@ make_ast_context :: proc(file: ast.File, imports: [] Package, package_name: stri globals = make(map [string] ^ast.Expr, 0, allocator), variables = make(map [string] bool, 0, allocator), usings = make([dynamic] string, allocator), + parameters = make(map [string] bool, 0, allocator), file = file, imports = imports, use_locals = true, @@ -501,18 +504,23 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i using ast; + v2, ok := node.derived.(ast.Pointer_Type); + switch v in node.derived { case Ident: return resolve_type_identifier(ast_context, v); case Basic_Lit: return resolve_basic_lit(ast_context, v); + case Type_Assertion: + resolve_type_expression(ast_context, v.type); case Pointer_Type: + if v2, ok := v.elem.derived.(ast.Pointer_Type); !ok { return resolve_type_expression(ast_context, v.elem); } else { - return resolve_type_expression(ast_context, node); + return make_symbol_generic_from_ast(ast_context, node), true; } case Index_Expr: @@ -639,11 +647,35 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i using ast; + if _, ok := ast_context.parameters[node.name]; ok { + for imp in ast_context.imports { + + if strings.compare(imp.base, node.name) == 0 { + + symbol := index.Symbol { + type = .Package, + scope = imp.name, + value = index.SymbolPackageValue { + } + }; + + return symbol, true; + } + + } + } + + //note(Daniel, if global and local ends up being 100% same just make a function that takes the map) if local, ok := ast_context.locals[node.name]; ast_context.use_locals && ok { switch v in local.derived { case Ident: + + if node.name == v.name { + break; + } + return resolve_type_identifier(ast_context, v); case Union_Type: return make_symbol_union_from_ast(ast_context, v), true; @@ -680,6 +712,11 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i switch v in global.derived { case Ident: + + if node.name == v.name { + break; + } + return resolve_type_identifier(ast_context, v); case Struct_Type: return make_symbol_struct_from_ast(ast_context, v), true; @@ -740,7 +777,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i scope = node.name, value = index.SymbolPackageValue { } - }; + }; return symbol, true; @@ -805,10 +842,18 @@ resolve_ident_is_variable :: proc(ast_context: ^AstContext, node: ast.Ident) -> resolve_ident_is_package :: proc(ast_context: ^AstContext, node: ast.Ident) -> bool { - for imp in ast_context.imports { + if strings.contains(node.name, "/") { + return true; + } + + else { + + for imp in ast_context.imports { + + if strings.compare(imp.base, node.name) == 0 { + return true; + } - if strings.compare(imp.base, node.name) == 0 { - return true; } } @@ -861,6 +906,24 @@ resolve_location_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) - return index.lookup(node.name, ast_context.document_package); } +make_bool_ast :: proc() -> ^ast.Ident { + + ident := index.new_type(ast.Ident, {}, {}, context.temp_allocator); + + ident.name = bool_lit; + + return ident; +} + +make_int_ast :: proc() -> ^ast.Ident { + + ident := index.new_type(ast.Ident, {}, {}, context.temp_allocator); + + ident.name = int_lit; + + return ident; +} + make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, v: ast.Proc_Lit, name: string) -> index.Symbol { symbol := index.Symbol { @@ -1061,6 +1124,11 @@ get_generic_assignment :: proc(file: ast.File, value: ^ast.Expr, ast_context: ^A if v.expr != nil { append(results, value); } + case Type_Assertion: + if v.type != nil { + append(results, v.type); + append(results, make_bool_ast()); + } case: log.debugf("default node get_generic_assignment %v", v); append(results, value); @@ -1072,6 +1140,11 @@ get_locals_value_decl :: proc(file: ast.File, value_decl: ast.Value_Decl, ast_co using ast; + if len(value_decl.names) <= 0 { + return; + } + + if value_decl.type != nil { str := common.get_ast_node_string(value_decl.names[0], file.src); ast_context.variables[str] = value_decl.is_mutable; @@ -1085,16 +1158,17 @@ get_locals_value_decl :: proc(file: ast.File, value_decl: ast.Value_Decl, ast_co get_generic_assignment(file, value, ast_context, &results); } - if len(value_decl.names) == len(results) { - for name, i in value_decl.names { + for name, i in value_decl.names { + if i < len(results) { str := common.get_ast_node_string(name, file.src); ast_context.locals[str] = results[i]; ast_context.variables[str] = value_decl.is_mutable; } - } + + } get_locals_stmt :: proc(file: ast.File, stmt: ^ast.Stmt, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { @@ -1104,15 +1178,19 @@ get_locals_stmt :: proc(file: ast.File, stmt: ^ast.Stmt, ast_context: ^AstContex using ast; + if stmt == nil { + return; + } + switch v in stmt.derived { case Value_Decl: get_locals_value_decl(file, v, ast_context); case Type_Switch_Stmt: get_locals_type_switch_stmt(file, v, ast_context, document_position); - // case Switch_Stmt: - // get_locals_switch_stmt(file, v, ast_context, document_position); - // case For_Stmt: - // get_locals_for_stmt(file, v, ast_context, document_position); + case Switch_Stmt: + get_locals_switch_stmt(file, v, ast_context, document_position); + case For_Stmt: + get_locals_for_stmt(file, v, ast_context, document_position); case Range_Stmt: get_locals_for_range_stmt(file, v, ast_context, document_position); case If_Stmt: @@ -1183,9 +1261,9 @@ get_locals_assign_stmt :: proc(file: ast.File, stmt: ast.Assign_Stmt, ast_contex } for lhs, i in stmt.lhs { - if ident, ok := lhs.derived.(ast.Ident); ok { ast_context.locals[ident.name] = results[i]; + ast_context.variables[ident.name] = true; } } @@ -1197,11 +1275,9 @@ get_locals_if_stmt :: proc(file: ast.File, stmt: ast.If_Stmt, ast_context: ^AstC return; } - if stmt.init != nil { - get_locals_stmt(file, stmt.init, ast_context, document_position); - } - + get_locals_stmt(file, stmt.init, ast_context, document_position); get_locals_stmt(file, stmt.body, ast_context, document_position); + get_locals_stmt(file, stmt.else_stmt, ast_context, document_position); } @@ -1225,6 +1301,7 @@ get_locals_for_range_stmt :: proc(file: ast.File, stmt: ast.Range_Stmt, ast_cont if ident, ok := stmt.val0.derived.(Ident); ok { indexed.expr = results[0]; ast_context.locals[ident.name] = indexed; + ast_context.variables[ident.name] = true; } } @@ -1232,7 +1309,8 @@ get_locals_for_range_stmt :: proc(file: ast.File, stmt: ast.Range_Stmt, ast_cont else if len(results) > 1 && stmt.val0 != nil && stmt.val1 != nil { if ident, ok := stmt.val1.derived.(Ident); ok { - //ast_context.locals[ident.name] = ident; + ast_context.locals[ident.name] = make_int_ast(); + ast_context.variables[ident.name] = true; } } @@ -1247,6 +1325,7 @@ get_locals_for_stmt :: proc(file: ast.File, stmt: ast.For_Stmt, ast_context: ^As return; } + get_locals_stmt(file, stmt.init, ast_context, document_position); get_locals_stmt(file, stmt.body, ast_context, document_position); } @@ -1286,6 +1365,7 @@ get_locals_type_switch_stmt :: proc(file: ast.File, stmt: ast.Type_Switch_Stmt, if len(tag.lhs) == 1 && len(cause.list) == 1 { ident := tag.lhs[0].derived.(Ident); ast_context.locals[ident.name] = cause.list[0]; + ast_context.variables[ident.name] = true; } } @@ -1313,6 +1393,7 @@ get_locals :: proc(file: ast.File, function: ^ast.Node, ast_context: ^AstContext str := common.get_ast_node_string(name, file.src); ast_context.locals[str] = arg.type; ast_context.variables[str] = true; + ast_context.parameters[str] = true; } } @@ -1336,6 +1417,9 @@ get_locals :: proc(file: ast.File, function: ^ast.Node, ast_context: ^AstContext clear_locals :: proc(ast_context: ^AstContext) { clear(&ast_context.locals); + clear(&ast_context.parameters); + clear(&ast_context.variables); + clear(&ast_context.usings); } get_definition_location :: proc(document: ^Document, position: common.Position) -> (common.Location, bool) { @@ -1508,7 +1592,6 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> ( } case index.SymbolStructValue: - list.isIncomplete = false; for name, i in v.names { diff --git a/src/server/requests.odin b/src/server/requests.odin index 7b1eafb..439c37d 100644 --- a/src/server/requests.odin +++ b/src/server/requests.odin @@ -294,8 +294,8 @@ request_initialize :: proc(params: json.Value, id: RequestId, config: ^common.Co triggerCharacters = signatureTriggerCharacters, }, semanticTokensProvider = SemanticTokensOptions { - //range = true, - full = true, + range = true, + full = false, legend = SemanticTokensLegend { tokenTypes = token_types, tokenModifiers = token_modifiers, @@ -542,7 +542,18 @@ request_semantic_token_full :: proc(params: json.Value, id: RequestId, config: ^ document_refresh(document, config, nil); - symbols := get_semantic_tokens(document); + range := common.Range { + start = common.Position { + line = 0, + }, + + end = common.Position { + line = 9000000, //should be enough + } + }; + + //symbols: SemanticTokens; + symbols := get_semantic_tokens(document, range); response := make_response_message( params = symbols, @@ -556,8 +567,31 @@ request_semantic_token_full :: proc(params: json.Value, id: RequestId, config: ^ request_semantic_token_range :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { + params_object, ok := params.value.(json.Object); + + if !ok { + return .ParseError; + } + + semantic_params: SemanticTokensRangeParams; + + if unmarshal(params, semantic_params, context.temp_allocator) != .None { + return .ParseError; + } + + document := document_get(semantic_params.textDocument.uri); + + if document == nil { + return .InternalError; + } + + document_refresh(document, config, nil); + + //symbols: SemanticTokens; + symbols := get_semantic_tokens(document, semantic_params.range); + response := make_response_message( - params = nil, + params = symbols, id = id, ); diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin index 1086063..cf92800 100644 --- a/src/server/semantic_tokens.odin +++ b/src/server/semantic_tokens.odin @@ -7,6 +7,10 @@ import "core:log" import "shared:common" import "shared:index" +/* + Right now I might be setting the wrong types, since there is no documentation as to what should be what, and looking at other LSP there is no consistancy. +*/ + SemanticTokenTypes :: enum { Namespace, Type, @@ -23,6 +27,7 @@ SemanticTokenTypes :: enum { String, Number, Operator, + Property, }; SemanticTokenModifiers :: enum { @@ -72,6 +77,7 @@ SemanticTokens :: struct { SemanticTokenBuilder :: struct { current_function: ^ast.Node, current_start: int, + selector_variable: bool, tokens: [dynamic] u32, }; @@ -89,7 +95,7 @@ get_tokens :: proc(builder: SemanticTokenBuilder) -> SemanticTokens { }; } -get_semantic_tokens :: proc(document: ^Document) -> SemanticTokens { +get_semantic_tokens :: proc(document: ^Document, range: common.Range) -> SemanticTokens { ast_context := make_ast_context(document.ast, document.imports, document.package_name, context.temp_allocator); builder := make_token_builder(); @@ -97,7 +103,9 @@ get_semantic_tokens :: proc(document: ^Document) -> SemanticTokens { get_globals(document.ast, &ast_context); for decl in document.ast.decls { - write_semantic_tokens(cast(^ast.Node)decl, &builder, &ast_context); + if range.start.line <= decl.pos.line && decl.end.line <= range.end.line { + write_semantic_tokens(decl, &builder, &ast_context); + } } return get_tokens(builder); @@ -134,14 +142,17 @@ write_semantic_token_pos :: proc(builder: ^SemanticTokenBuilder, pos: tokenizer. } -resolve_and_write_ident :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) { +resolve_and_write_ident :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) -> (is_variable: bool) { n := node.derived.(ast.Ident); ast_context.current_package = ast_context.document_package; + ast_context.use_globals = true; + ast_context.use_locals = true; if resolve_ident_is_variable(ast_context, n) { write_semantic_node(builder, node, ast_context.file.src, .Variable, .None); + is_variable = true; } else if symbol, ok := resolve_type_identifier(ast_context, n); ok { @@ -155,6 +166,10 @@ resolve_and_write_ident :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, 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 index.SymbolGenericValue: #partial switch symbol.type { case .Keyword: @@ -163,34 +178,11 @@ resolve_and_write_ident :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, } } -} - -resolve_and_write_expr :: proc(expr: ^ast.Expr, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) { - - ast_context.current_package = ast_context.document_package; - - if symbol, ok := resolve_type_expression(ast_context, expr); ok { - - #partial switch v in symbol.value { - case index.SymbolPackageValue: - write_semantic_node(builder, expr, ast_context.file.src, .Namespace, .None); - case index.SymbolStructValue: - write_semantic_node(builder, expr, ast_context.file.src, .Struct, .None); - case index.SymbolEnumValue: - write_semantic_node(builder, expr, ast_context.file.src, .Enum, .None); - case index.SymbolUnionValue: - write_semantic_node(builder, expr, ast_context.file.src, .Enum, .None); - case index.SymbolGenericValue: - #partial switch symbol.type { - case .Keyword: - write_semantic_node(builder, expr, ast_context.file.src, .Keyword, .None); - } - } - - } + return; } + write_semantic_tokens :: proc { write_semantic_tokens_node, write_semantic_tokens_dynamic_array, @@ -200,7 +192,7 @@ write_semantic_tokens :: proc { write_semantic_tokens_array :: proc(array: $A/[]^$T, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) { for elem, i in array { - write_semantic_tokens(elem, builder, ast_context); + write_semantic_tokens_node(elem, builder, ast_context); } } @@ -208,7 +200,7 @@ write_semantic_tokens_array :: proc(array: $A/[]^$T, builder: ^SemanticTokenBuil write_semantic_tokens_dynamic_array :: proc(array: $A/[dynamic]^$T, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) { for elem, i in array { - write_semantic_tokens(elem, builder, ast_context); + write_semantic_tokens_node(elem, builder, ast_context); } } @@ -223,6 +215,13 @@ write_semantic_tokens_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuild switch n in node.derived { case Ident: + /*EXPENSIVE!! But alas i can't just get locals per scope, but have to the exact position, because you can do shit like this: + log.println("hello"); //log is namespace + log := 2; //log is now variable + a := log + 2; + */ + + get_locals_at(builder.current_function, node, ast_context); resolve_and_write_ident(node, builder, ast_context); case Selector_Expr: write_semantic_selector(cast(^Selector_Expr)node, builder, ast_context); @@ -236,7 +235,7 @@ write_semantic_tokens_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuild case Expr_Stmt: write_semantic_tokens(n.expr, builder, ast_context); case Range_Stmt: - get_locals_at(builder.current_function, node, ast_context); + write_semantic_token_pos(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None); if n.val0 != nil { if ident, ok := n.val0.derived.(Ident); ok { @@ -251,62 +250,188 @@ write_semantic_tokens_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuild } write_semantic_token_pos(builder, n.in_pos, "in", ast_context.file.src, .Keyword, .None); - write_semantic_tokens(n.expr, builder, ast_context); + write_semantic_tokens(n.body, builder, ast_context); + case If_Stmt: + write_semantic_token_pos(builder, n.if_pos, "if", ast_context.file.src, .Keyword, .None); + write_semantic_tokens(n.init, builder, ast_context); + write_semantic_tokens(n.cond, builder, ast_context); + write_semantic_tokens(n.body, builder, ast_context); + if n.else_stmt != nil { + write_semantic_token_pos(builder, n.else_pos, "else", ast_context.file.src, .Keyword, .None); + write_semantic_tokens(n.else_stmt, builder, ast_context); + } + case For_Stmt: + write_semantic_token_pos(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None); + write_semantic_tokens(n.init, builder, ast_context); + write_semantic_tokens(n.cond, builder, ast_context); + write_semantic_tokens(n.post, builder, ast_context); + write_semantic_tokens(n.body, builder, ast_context); + case Switch_Stmt: + write_semantic_token_pos(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None); + write_semantic_tokens(n.init, builder, ast_context); + write_semantic_tokens(n.cond, builder, ast_context); + write_semantic_tokens(n.body, builder, ast_context); + case Type_Switch_Stmt: + write_semantic_token_pos(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None); + write_semantic_tokens(n.tag, builder, ast_context); + write_semantic_tokens(n.expr, builder, ast_context); + write_semantic_tokens(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 { + write_semantic_tokens(l, builder, ast_context); + } + } + write_semantic_token_op(builder, n.op, ast_context.file.src); + write_semantic_tokens(n.rhs, builder, ast_context); + case Case_Clause: + write_semantic_token_pos(builder, n.case_pos, "case", ast_context.file.src, .Keyword, .None); + write_semantic_tokens(n.list, builder, ast_context); write_semantic_tokens(n.body, builder, ast_context); + case Call_Expr: + write_semantic_tokens(n.expr, builder, ast_context); + write_semantic_tokens(n.args, builder, ast_context); + case Implicit_Selector_Expr: + write_semantic_node(builder, n.field, ast_context.file.src, .Enum, .None); + case Array_Type: + write_semantic_tokens(n.elem, builder, ast_context); + case Binary_Expr: + write_semantic_tokens(n.left, builder, ast_context); + write_semantic_token_op(builder, n.op, ast_context.file.src); + write_semantic_tokens(n.right, builder, ast_context); + case Comp_Lit: + write_semantic_tokens(n.type, builder, ast_context); + write_semantic_tokens(n.elems, builder, ast_context); + case Struct_Type: + write_semantic_token_pos(builder, n.pos, "struct", ast_context.file.src, .Keyword, .None); + write_semantic_struct_fields(n, builder, ast_context); + case Type_Assertion: + write_semantic_tokens(n.expr, builder, ast_context); + write_semantic_tokens(n.type, builder, ast_context); + case Type_Cast: + write_semantic_token_pos(builder, n.pos, "cast", ast_context.file.src, .Keyword, .None); + write_semantic_tokens(n.type, builder, ast_context); + write_semantic_tokens(n.expr, builder, ast_context); + case Paren_Expr: + write_semantic_tokens(n.expr, builder, ast_context); + case Deref_Expr: + write_semantic_tokens(n.expr, builder, ast_context); + case Return_Stmt: + write_semantic_token_pos(builder, n.pos, "return", ast_context.file.src, .Keyword, .None); + write_semantic_tokens(n.results, builder, ast_context); + case Dynamic_Array_Type: + write_semantic_token_pos(builder, n.dynamic_pos, "dynamic", ast_context.file.src, .Keyword, .None); + write_semantic_tokens(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); + } + + write_semantic_tokens(n.value, builder, ast_context); + case Index_Expr: + write_semantic_tokens(n.expr, builder, ast_context); + case Basic_Lit: + write_semantic_token_basic_lit(n, builder, ast_context); case: - //log.infof("unhandled write node %v", n); + log.infof("unhandled write node %v", n); } } -write_semantic_tokens_value_decl :: proc(value_decl: ast.Value_Decl, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) { +write_semantic_token_basic_lit :: proc(basic_lit: ast.Basic_Lit, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) { - using ast; + if symbol, ok := resolve_basic_lit(ast_context, basic_lit); ok { - for name, i in value_decl.names { - if ident, ok := name.derived.(Ident); ok { + if generic, ok := symbol.value.(index.SymbolGenericValue); ok { - if value_decl.type != nil { + ident := generic.expr.derived.(ast.Ident); + if ident.name == string_lit { + write_semantic_node(builder, generic.expr, ast_context.file.src, .String, .None); } - else { + else if ident.name == int_lit { + write_semantic_node(builder, generic.expr, ast_context.file.src, .Number, .None); + } - if len(value_decl.values) == 1 { - - switch v in value_decl.values[0].derived { - case ast.Struct_Type: - write_semantic_node(builder, name, ast_context.file.src, .Struct, .None); - write_semantic_token_pos(builder, v.pos, "struct", ast_context.file.src, .Keyword, .None); - case ast.Enum_Type: - write_semantic_node(builder, name, ast_context.file.src, .Enum, .None); - write_semantic_token_pos(builder, v.pos, "enum", ast_context.file.src, .Keyword, .None); - write_semantic_enum_fields(v, builder, ast_context); - case ast.Proc_Lit: - write_semantic_node(builder, name, ast_context.file.src, .Function, .None); - write_semantic_token_pos(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None); - write_semantic_proc_type(v.type, builder, ast_context); - - last_function := builder.current_function; - builder.current_function = value_decl.values[0]; - get_locals_at(builder.current_function, builder.current_function, ast_context); - write_semantic_tokens(v.body, builder, ast_context); - builder.current_function = last_function; - } + } - } + } +} - else { +write_semantic_tokens_value_decl :: proc(value_decl: ast.Value_Decl, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) { - } + using ast; + 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_token_pos(builder, v.pos, "struct", ast_context.file.src, .Keyword, .None); + write_semantic_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_token_pos(builder, v.pos, "enum", ast_context.file.src, .Keyword, .None); + write_semantic_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_token_pos(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_token_pos(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None); + write_semantic_proc_type(v.type, builder, ast_context); + + last_function := builder.current_function; + builder.current_function = value_decl.values[0]; + write_semantic_tokens(v.body, builder, ast_context); + builder.current_function = last_function; + case: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Variable, .None); + write_semantic_tokens(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 { + write_semantic_tokens(value, builder, ast_context); } + + + } + + + + +} + + +write_semantic_token_op :: proc(builder: ^SemanticTokenBuilder, token: tokenizer.Token, src: []byte) { + + if token.text == "=" { + write_semantic_token_pos(builder, token.pos, token.text, src, .Operator, .None); + } + + else if token.text == "in" { + write_semantic_token_pos(builder, token.pos, token.text, src, .Keyword, .None); } } @@ -375,21 +500,68 @@ write_semantic_enum_fields :: proc(node: ast.Enum_Type, builder: ^SemanticTokenB } +write_semantic_struct_fields :: proc(node: ast.Struct_Type, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) { + + using ast; + + if node.fields == nil { + return; + } + + for field in node.fields.list { + //field. + + for name in field.names { + if ident, ok := name.derived.(Ident); ok { + write_semantic_node(builder, name, ast_context.file.src, .Property, .None); + } + } + + + write_semantic_tokens(field.type, builder, ast_context); + + } + +} + write_semantic_selector :: proc(selector: ^ast.Selector_Expr, builder: ^SemanticTokenBuilder, ast_context: ^AstContext) { using ast; if ident, ok := selector.expr.derived.(Ident); ok { - resolve_and_write_ident(selector.expr, builder, ast_context); //base - resolve_and_write_expr(selector, builder, ast_context); //field + builder.selector_variable = resolve_and_write_ident(selector.expr, builder, ast_context); //base } else { - + write_semantic_tokens(selector.expr, builder, ast_context); } + if symbol, ok := resolve_type_expression(ast_context, selector); ok && !builder.selector_variable { + #partial switch v in symbol.value { + case index.SymbolPackageValue: + write_semantic_node(builder, selector.field, ast_context.file.src, .Namespace, .None); + case index.SymbolStructValue: + write_semantic_node(builder, selector.field, ast_context.file.src, .Struct, .None); + case index.SymbolEnumValue: + write_semantic_node(builder, selector.field, ast_context.file.src, .Enum, .None); + case index.SymbolUnionValue: + write_semantic_node(builder, selector.field, ast_context.file.src, .Enum, .None); + case index.SymbolProcedureGroupValue: + write_semantic_node(builder, selector.field, ast_context.file.src, .Function, .None); + case index.SymbolGenericValue: + #partial switch symbol.type { + case .Keyword: + write_semantic_node(builder, selector.field, ast_context.file.src, .Keyword, .None); + } + } + + } + + else if (builder.selector_variable) { + write_semantic_node(builder, selector.field, ast_context.file.src, .Property, .None); + } } |