aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/ast.odin3
-rw-r--r--src/index/indexer.odin4
-rw-r--r--src/main.odin4
-rw-r--r--src/server/analysis.odin121
-rw-r--r--src/server/requests.odin42
-rw-r--r--src/server/semantic_tokens.odin304
6 files changed, 384 insertions, 94 deletions
diff --git a/src/common/ast.odin b/src/common/ast.odin
index ef98acb..3126847 100644
--- a/src/common/ast.odin
+++ b/src/common/ast.odin
@@ -17,7 +17,8 @@ keyword_map : map [string] bool =
"any" = true,
"u32" = true,
"true" = true,
- "false" = true};
+ "false" = true,
+ "nil" = true};
get_ast_node_string :: proc(node: ^ast.Node, src: [] byte) -> string {
return string(src[node.pos.offset:node.end.offset]);
diff --git a/src/index/indexer.odin b/src/index/indexer.odin
index 88e5419..e7d23e3 100644
--- a/src/index/indexer.odin
+++ b/src/index/indexer.odin
@@ -44,9 +44,9 @@ Indexer :: struct {
indexer: Indexer;
-lookup :: proc(name: string, scope: string) -> (Symbol, bool) {
+lookup :: proc(name: string, scope: string, loc := #caller_location) -> (Symbol, bool) {
symbol, ok := memory_index_lookup(&indexer.static_index, name, scope);
- //log.infof("lookup name: %v scope: %v, symbol %v", name, scope, symbol);
+ log.infof("lookup name: %v scope: %v, symbol %v location %v", name, scope, symbol, loc);
return symbol, ok;
}
diff --git a/src/main.odin b/src/main.odin
index 7518454..6098c11 100644
--- a/src/main.odin
+++ b/src/main.odin
@@ -95,12 +95,12 @@ main :: proc() {
reader := server.make_reader(os_read, cast(rawptr)os.stdin);
writer := server.make_writer(os_write, cast(rawptr)os.stdout);
- init_global_temporary_allocator(mem.megabytes(10));
+ init_global_temporary_allocator(mem.megabytes(200));
//fd, err := os.open("C:/Users/danie/OneDrive/Desktop/Computer_Science/ols/log.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC );
//context.logger = log.create_file_logger(fd);
- context.logger = server.create_lsp_logger(&writer);
+ //context.logger = server.create_lsp_logger(&writer);
run(&reader, &writer);
}
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);
+ }
}