aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2022-01-05 09:33:03 +0100
committerDaniel Gavin <danielgavin5@hotmail.com>2022-01-05 09:33:03 +0100
commit93df32b34b80da4d62644004160294d1d068a934 (patch)
treeed42f20ebda9993b1ad0ebe552043be5e9bd7bc5 /src
parent508b2487f45fac7a58549e4c5f8cde3f250ae568 (diff)
more refractoring by trying to store the variable information on the symbol.
Diffstat (limited to 'src')
-rw-r--r--src/analysis/analysis.odin142
-rw-r--r--src/common/position.odin1
-rw-r--r--src/common/types.odin3
-rw-r--r--src/index/collector.odin6
-rw-r--r--src/index/indexer.odin9
-rw-r--r--src/index/symbol.odin34
-rw-r--r--src/server/completion.odin61
-rw-r--r--src/server/definition.odin3
-rw-r--r--src/server/document_symbols.odin3
-rw-r--r--src/server/documents.odin12
-rw-r--r--src/server/hover.odin2
-rw-r--r--src/server/inlay_hints.odin2
-rw-r--r--src/server/lens.odin2
-rw-r--r--src/server/requests.odin4
-rw-r--r--src/server/semantic_tokens.odin490
-rw-r--r--src/server/signature.odin2
16 files changed, 163 insertions, 613 deletions
diff --git a/src/analysis/analysis.odin b/src/analysis/analysis.odin
index f80e1d0..c0da0b6 100644
--- a/src/analysis/analysis.odin
+++ b/src/analysis/analysis.odin
@@ -64,6 +64,7 @@ DocumentPositionContext :: struct {
DocumentLocal :: struct {
expr: ^ast.Expr,
offset: int,
+ id: int, //Id that can used to connect the local to something, i.e. for stmt begin offset
}
AstContext :: struct {
@@ -85,10 +86,10 @@ AstContext :: struct {
value_decl: ^ast.Value_Decl,
field_name: string,
uri: string,
+ symbol_cache: ^map[int]rawptr, //symbol_cache from the current document
}
-make_ast_context :: proc(file: ast.File, imports: []common.Package, package_name: string, uri: string, allocator := context.temp_allocator) -> AstContext {
-
+make_ast_context :: proc(file: ast.File, imports: []common.Package, package_name: string, uri: string, symbol_cache: ^map[int]rawptr, allocator := context.temp_allocator) -> AstContext {
ast_context := AstContext {
locals = make(map[string][dynamic]DocumentLocal, 0, allocator),
globals = make(map[string]common.GlobalExpr, 0, allocator),
@@ -103,6 +104,7 @@ make_ast_context :: proc(file: ast.File, imports: []common.Package, package_name
document_package = package_name,
current_package = package_name,
uri = uri,
+ symbol_cache = symbol_cache,
};
when ODIN_OS == "windows" {
@@ -785,7 +787,6 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou
}
resolve_basic_lit :: proc(ast_context: ^AstContext, basic_lit: ast.Basic_Lit) -> (index.Symbol, bool) {
-
symbol := index.Symbol {
type = .Constant,
};
@@ -818,8 +819,37 @@ resolve_basic_directive :: proc(ast_context: ^AstContext, directive: ast.Basic_D
return {}, false;
}
+//Experiment with caching the results of the current file, this might just make it slower,
+//but it will help with multiple requests like semantic tokens.
+//If this doesn't provide good results, just handle caching explicitly on semantic tokens only.
+lookup_symbol_cache :: proc(ast_context: ^AstContext, node: ast.Node) -> (index.Symbol, bool) {
+ if ast_context.document_package != node.pos.file || node.pos.file == "" {
+ return {}, false;
+ }
+
+ if cached := &ast_context.symbol_cache[node.pos.offset]; cached != nil {
+ symbol := cast(^index.Symbol)cached^;
+ return symbol^, true;
+ }
+ return {}, false;
+}
+
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;
+ }
+
+ if symbol, ok := internal_resolve_type_expression(ast_context, node); ok {
+ cached_symbol := index.new_clone_symbol(symbol);
+ ast_context.symbol_cache[node.pos.offset] = cast(rawptr)cached_symbol;
+ return symbol, true;
+ }
+
+ return {}, false;
+}
+
+internal_resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (index.Symbol, bool) {
if node == nil {
return {}, false;
}
@@ -1010,8 +1040,7 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i
return index.Symbol {}, false;
}
-store_local :: proc(ast_context: ^AstContext, expr: ^ast.Expr, offset: int, name: string) {
-
+store_local :: proc(ast_context: ^AstContext, expr: ^ast.Expr, offset: int, name: string, id := 0) {
local_stack := &ast_context.locals[name];
if local_stack == nil {
@@ -1019,11 +1048,10 @@ store_local :: proc(ast_context: ^AstContext, expr: ^ast.Expr, offset: int, name
local_stack = &ast_context.locals[name];
}
- append(local_stack, DocumentLocal {expr = expr, offset = offset});
+ append(local_stack, DocumentLocal {expr = expr, offset = offset, id = id});
}
-get_local :: proc(ast_context: ^AstContext, offset: int, name: string) -> ^ast.Expr {
-
+get_local :: proc(ast_context: ^AstContext, offset: int, name: string, id := 0) -> ^ast.Expr {
previous := 0;
//is the local we are getting being declared?
@@ -1041,7 +1069,7 @@ get_local :: proc(ast_context: ^AstContext, offset: int, name: string) -> ^ast.E
if local_stack, ok := ast_context.locals[name]; ok {
for i := len(local_stack) - 1; i >= 0; i -= 1 {
- if local_stack[i].offset <= offset {
+ if local_stack[i].offset <= offset && local_stack[i].id == id {
if i - previous < 0 {
return nil;
} else {
@@ -1055,7 +1083,20 @@ get_local :: proc(ast_context: ^AstContext, offset: int, name: string) -> ^ast.E
}
resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (index.Symbol, bool) {
+ if symbol, ok := lookup_symbol_cache(ast_context, node); ok {
+ return symbol, true;
+ }
+
+ if symbol, ok := internal_resolve_type_identifier(ast_context, node); ok {
+ cached_symbol := index.new_clone_symbol(symbol);
+ ast_context.symbol_cache[node.pos.offset] = cast(rawptr)cached_symbol;
+ return symbol, true;
+ }
+ return {}, false;
+}
+
+internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (index.Symbol, bool) {
using ast;
if pkg, ok := ast_context.in_package[node.name]; ok {
@@ -1078,7 +1119,6 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
//note(Daniel, if global and local ends up being 100% same just make a function that takes the map)
if local := get_local(ast_context, node.pos.offset, node.name); local != nil && ast_context.use_locals {
-
is_distinct := false;
if dist, ok := local.derived.(ast.Distinct_Type); ok {
@@ -1138,7 +1178,6 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
return return_symbol, ok;
} else if global, ok := ast_context.globals[node.name]; ast_context.use_globals && ok {
-
is_distinct := false;
if dist, ok := global.expr.derived.(ast.Distinct_Type); ok {
@@ -1235,7 +1274,6 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
} else {
//right now we replace the package ident with the absolute directory name, so it should have '/' which is not a valid ident character
if strings.contains(node.name, "/") {
-
symbol := index.Symbol {
type = .Package,
pkg = node.name,
@@ -1246,9 +1284,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
} else {
//part of the ast so we check the imports of the document
for imp in ast_context.imports {
-
if strings.compare(imp.base, node.name) == 0 {
-
symbol := index.Symbol {
type = .Package,
pkg = imp.name,
@@ -1275,39 +1311,21 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
}
for u in ast_context.usings {
-
//TODO(Daniel, make into a map, not really required for performance but looks nicer)
for imp in ast_context.imports {
-
if strings.compare(imp.base, u) == 0 {
-
if symbol, ok := index.lookup(node.name, imp.name); ok {
return resolve_symbol_return(ast_context, symbol);
}
}
}
}
-
}
return index.Symbol {}, false;
}
-resolve_ident_is_variable :: proc(ast_context: ^AstContext, node: ast.Ident) -> bool {
-
- if v, ok := ast_context.variables[node.name]; ok && v {
- return true;
- }
-
- if symbol, ok := index.lookup(node.name, ast_context.current_package); ok {
- return symbol.type == .Variable;
- }
-
- return false;
-}
-
resolve_ident_is_package :: proc(ast_context: ^AstContext, node: ast.Ident) -> bool {
-
if strings.contains(node.name, "/") {
return true;
} else {
@@ -1985,7 +2003,6 @@ get_generic_assignment :: proc(file: ast.File, value: ^ast.Expr, ast_context: ^A
switch v in &value.derived {
case Call_Expr:
-
ast_context.call = cast(^ast.Call_Expr)value;
if symbol, ok := resolve_type_expression(ast_context, v.expr); ok {
@@ -2400,34 +2417,71 @@ 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);
+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);
ast_context.current_package = ast_context.document_package;
- symbols := make([]^index.Symbol, allocator);
+ symbols := make([dynamic]index.Symbol, allocator);
for decl in document.ast.decls {
switch v in decl.derived {
case ast.Proc_Lit:
- resolve_entire_procedure(v.type, &symbols, allocator);
+ resolve_entire_procedure(&ast_context, v, &symbols, allocator);
}
}
+
+ return symbols[:];
}
-resolve_entire_procedure :: proc(procedure: ^ast.Proc_Type, symbols: ^[]^index.Symbol, allocator := context.allocator) {
- if procedure == nil {
- return {};
+resolve_entire_procedure :: proc(ast_context: ^AstContext, procedure: ast.Proc_Lit, symbols: ^[dynamic]index.Symbol, allocator := context.allocator) {
+ Visit_Data :: struct {
+ ast_context: ^AstContext,
+ symbols: ^[dynamic]index.Symbol,
}
- get_locals()
+ data := Visit_Data {
+ ast_context = ast_context,
+ symbols = symbols,
+ };
+
+ visit :: proc(visitor: ^ast.Visitor, node: ^ast.Node) -> ^ast.Visitor {
+ if node == nil || visitor == nil {
+ return nil;
+ }
+
+ data := cast(^Visit_Data)visitor.data;
+ ast_context := data.ast_context;
+
+ switch v in &node.derived {
+ case ast.Ident:
+ if symbol, ok := resolve_type_identifier(ast_context, v); ok {
+ append(data.symbols, symbol);
+ }
+ case ast.Selector_Expr:
+ if symbol, ok := resolve_type_expression(ast_context, &v.node); ok {
+ append(data.symbols, symbol);
+ }
+ }
+
+ return visitor;
+ }
+ visitor := ast.Visitor {
+ data = &data,
+ visit = visit,
+ }
+ ast.walk(&visitor, procedure.body);
+
+ if procedure.type != nil {
+ ast.walk(&visitor, procedure.type.params);
+ ast.walk(&visitor, procedure.type.results);
+ }
}
-*/
+
concatenate_symbol_information :: proc {
concatenate_raw_symbol_information,
@@ -2512,7 +2566,7 @@ get_signature :: proc(ast_context: ^AstContext, ident: ast.Ident, symbol: index.
return symbol.name;
}
- is_variable := resolve_ident_is_variable(ast_context, ident);
+ is_variable := symbol.type == .Variable;
#partial switch v in symbol.value {
case SymbolBasicValue:
diff --git a/src/common/position.odin b/src/common/position.odin
index 41bf00a..4e84568 100644
--- a/src/common/position.odin
+++ b/src/common/position.odin
@@ -55,7 +55,6 @@ get_absolute_position :: proc(position: Position, document_text: []u8) -> (Absol
}
get_relative_token_position :: proc(offset: int, document_text: []u8, current_start: int) -> Position {
-
start_index := current_start;
data := document_text[start_index:];
diff --git a/src/common/types.odin b/src/common/types.odin
index 317269b..0956e89 100644
--- a/src/common/types.odin
+++ b/src/common/types.odin
@@ -37,8 +37,9 @@ Document :: struct {
ast: ast.File,
imports: []Package,
package_name: string,
- allocator: ^Scratch_Allocator, //because does not support freeing I use arena allocators for each document
+ allocator: ^Scratch_Allocator, //because parser does not support freeing I use arena allocators for each document
operating_on: int, //atomic
+ symbol_cache: map[int]rawptr, //Stores all the symbol data for this current iteration of the file. Gets cleared every change.
}
parser_warning_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) {
diff --git a/src/index/collector.odin b/src/index/collector.odin
index a76fef5..91a5419 100644
--- a/src/index/collector.odin
+++ b/src/index/collector.odin
@@ -336,7 +336,11 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri
}
case: // default
symbol.value = collect_generic(collection, col_expr, package_map);
- token_type = .Unresolved;
+ if expr.mutable {
+ token_type = .Variable;
+ } else {
+ token_type = .Unresolved;
+ }
token = expr.expr;
}
diff --git a/src/index/indexer.odin b/src/index/indexer.odin
index 611b922..6c74436 100644
--- a/src/index/indexer.odin
+++ b/src/index/indexer.odin
@@ -33,6 +33,8 @@ import "core:sort"
This index is first searched and if nothing is found look in the static index.
*/
+
+
Indexer :: struct {
built_in_packages: [dynamic]string,
static_index: MemoryIndex,
@@ -47,7 +49,6 @@ FuzzyResult :: struct {
}
lookup :: proc(name: string, pkg: string, loc := #caller_location) -> (Symbol, bool) {
-
if symbol, ok := memory_index_lookup(&indexer.dynamic_index, name, pkg); ok {
log.infof("lookup dynamic name: %v pkg: %v, symbol %v location %v", name, pkg, symbol, loc);
return symbol, true;
@@ -64,9 +65,9 @@ lookup :: proc(name: string, pkg: string, loc := #caller_location) -> (Symbol, b
fuzzy_search :: proc(name: string, pkgs: []string) -> ([]FuzzyResult, bool) {
dynamic_results, dynamic_ok := memory_index_fuzzy_search(&indexer.dynamic_index, name, pkgs);
- static_results, static_ok := memory_index_fuzzy_search(&indexer.static_index, name, pkgs);
- result := make([dynamic]FuzzyResult, context.temp_allocator);
- files := make(map[string]bool, 0, context.temp_allocator);
+ static_results, static_ok := memory_index_fuzzy_search(&indexer.static_index, name, pkgs);
+ result := make([dynamic]FuzzyResult, context.temp_allocator);
+ files := make(map[string]bool, 0, context.temp_allocator);
if !dynamic_ok || !static_ok {
return {}, false;
diff --git a/src/index/symbol.odin b/src/index/symbol.odin
index 37392e4..863701c 100644
--- a/src/index/symbol.odin
+++ b/src/index/symbol.odin
@@ -103,24 +103,25 @@ SymbolFlag :: enum {
Deprecated,
PrivateFile,
PrivatePackage,
- Anonymous,
+ Anonymous, //Usually applied to structs that are defined inline inside another struct
+ Variable, //Symbols that are variable, this means their value decl was mutable
}
SymbolFlags :: bit_set[SymbolFlag]
Symbol :: struct {
- range: common.Range, //the range of the symbol in the file
- uri: string, //uri of the file the symbol resides
- pkg: string, //absolute directory path where the symbol resides
- name: string, //name of the symbol
- doc: string,
- signature: string, //type signature
- returns: string, //precedure return signature
- type: SymbolType,
- value: SymbolValue,
- references: []common.Location, //all the places in the project that it's being referenced
- pointers: int, //how many `^` are applied to the symbol
- flags: SymbolFlags,
+ range: common.Range, //the range of the symbol in the file
+ uri: string, //uri of the file the symbol resides
+ pkg: string, //absolute directory path where the symbol resides
+ name: string, //name of the symbol
+ doc: string,
+ signature: string, //type signature
+ returns: string, //precedure return signature
+ type: SymbolType,
+ value: SymbolValue,
+ references: []common.Location, //all the places in the project that it's being referenced
+ pointers: int, //how many `^` are applied to the symbol
+ flags: SymbolFlags,
}
SymbolType :: enum {
@@ -137,6 +138,13 @@ SymbolType :: enum {
Unresolved = 9999,
}
+new_clone_symbol :: proc(data: Symbol, allocator := context.allocator) -> (^Symbol) {
+ new_symbol := new(Symbol, allocator);
+ new_symbol^ = data;
+ new_symbol.value = data.value;
+ return new_symbol;
+}
+
free_symbol :: proc(symbol: Symbol, allocator: mem.Allocator) {
if symbol.signature != "" && symbol.signature != "struct" &&
diff --git a/src/server/completion.odin b/src/server/completion.odin
index 87490ac..0885e00 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -50,7 +50,7 @@ get_completion_list :: proc(document: ^common.Document, position: common.Positio
return list, true;
}
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
get_globals(document.ast, &ast_context);
@@ -232,10 +232,13 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if ident, ok := position_context.selector.derived.(ast.Ident); ok {
- is_variable := resolve_ident_is_variable(ast_context, ident);
- is_package := resolve_ident_is_package(ast_context, ident);
+ symbol, ok := resolve_type_identifier(ast_context, ident);
- if (!is_variable && !is_package && selector.type != .Enum && ident.name != "") || (is_variable && selector.type == .Enum) {
+ if !ok {
+ return;
+ }
+
+ if (symbol.type != .Variable && symbol.type != .Package && selector.type != .Enum && ident.name != "") || (symbol.type == .Variable && selector.type == .Enum) {
return;
}
}
@@ -386,7 +389,6 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
list.isIncomplete = false;
for name in v.names {
-
item := CompletionItem {
label = name,
kind = .EnumMember,
@@ -439,11 +441,9 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
case index.SymbolPackageValue:
-
list.isIncomplete = true;
if searched, ok := index.fuzzy_search(field, {selector.pkg}); ok {
-
for search in searched {
symbol := search.symbol;
@@ -477,7 +477,6 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) {
-
using analysis;
items := make([dynamic]CompletionItem, context.temp_allocator);
@@ -497,17 +496,12 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
//enum switch infer
if position_context.switch_stmt != nil && position_context.case_clause != nil && position_context.switch_stmt.cond != nil {
-
used_enums := make(map[string]bool, 5, context.temp_allocator);
if block, ok := position_context.switch_stmt.body.derived.(ast.Block_Stmt); ok {
-
for stmt in block.stmts {
-
if case_clause, ok := stmt.derived.(ast.Case_Clause); ok {
-
for name in case_clause.list {
-
if implicit, ok := name.derived.(ast.Implicit_Selector_Expr); ok {
used_enums[implicit.field.name] = true;
}
@@ -517,9 +511,7 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if enum_value, ok := unwrap_enum(ast_context, position_context.switch_stmt.cond); ok {
-
for name in enum_value.names {
-
if name in used_enums {
continue;
}
@@ -658,7 +650,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if position_context.binary != nil && (position_context.binary.op.text == "==" || position_context.binary.op.text == "!=") {
-
context_node: ^ast.Expr;
enum_node: ^ast.Expr;
@@ -673,7 +664,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
if context_node != nil && enum_node != nil {
if enum_value, ok := unwrap_enum(ast_context, enum_node); ok {
for name in enum_value.names {
-
item := CompletionItem {
label = name,
kind = .EnumMember,
@@ -690,19 +680,15 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if position_context.assign != nil && position_context.assign.rhs != nil && position_context.assign.lhs != nil {
-
rhs_index: int;
for elem in position_context.assign.rhs {
if position_in_node(elem, position_context.position) {
break;
} else {
-
//procedures are the only types that can return more than one value
if symbol, ok := resolve_type_expression(ast_context, elem); ok {
-
if procedure, ok := symbol.value.(index.SymbolProcedureValue); ok {
-
if procedure.return_types == nil {
return;
}
@@ -718,7 +704,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
if len(position_context.assign.lhs) > rhs_index {
if enum_value, ok := unwrap_enum(ast_context, position_context.assign.lhs[rhs_index]); ok {
for name in enum_value.names {
-
item := CompletionItem {
label = name,
kind = .EnumMember,
@@ -735,7 +720,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if position_context.returns != nil && position_context.function != nil {
-
return_index: int;
if position_context.returns.results == nil {
@@ -743,7 +727,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
for result, i in position_context.returns.results {
-
if position_in_node(result, position_context.position) {
return_index = i;
break;
@@ -759,11 +742,8 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if len(position_context.function.type.results.list) > return_index {
-
if enum_value, ok := unwrap_enum(ast_context, position_context.function.type.results.list[return_index].type); ok {
-
for name in enum_value.names {
-
item := CompletionItem {
label = name,
kind = .EnumMember,
@@ -780,21 +760,15 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
if position_context.call != nil {
-
if call, ok := position_context.call.derived.(ast.Call_Expr); ok {
-
parameter_index, parameter_ok := find_position_in_call_param(ast_context, call);
-
if symbol, ok := resolve_type_expression(ast_context, call.expr); ok && parameter_ok {
-
if proc_value, ok := symbol.value.(index.SymbolProcedureValue); ok {
-
if len(proc_value.arg_types) <= parameter_index {
return;
}
if enum_value, ok := unwrap_enum(ast_context, proc_value.arg_types[parameter_index].type); ok {
-
for name in enum_value.names {
item := CompletionItem {
label = name,
@@ -815,7 +789,6 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont
}
get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) {
-
using analysis;
items := make([dynamic]CompletionItem, context.temp_allocator);
@@ -824,7 +797,6 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
CombinedResult :: struct {
score: f32,
- variable: ^ast.Ident,
snippet: Snippet_Info,
name: string,
type: index.SymbolType,
@@ -931,7 +903,6 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
pkg = symbol.pkg,
signature = symbol.signature,
returns = symbol.returns,
- variable = ident,
});
}
}
@@ -965,7 +936,6 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
pkg = symbol.pkg,
signature = symbol.signature,
returns = symbol.returns,
- variable = ident,
});
}
}
@@ -1049,7 +1019,6 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
top_results := combined[0:(min(50, len(combined)))];
for result in top_results {
-
result := result;
//Skip procedures when the position is in proc decl
@@ -1085,16 +1054,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
documentation = result.doc,
};
- if result.variable != nil {
- if ok := resolve_ident_is_variable(ast_context, result.variable^); ok {
- item.kind = .Variable;
- result.type = .Variable;
- } else {
- item.kind = cast(CompletionItemKind)result.type;
- }
- } else {
- item.kind = cast(CompletionItemKind)result.type;
- }
+ item.kind = cast(CompletionItemKind)result.type;
if result.type == .Function {
item.insertText = fmt.tprintf("%v($0)", item.label);
@@ -1143,7 +1103,6 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte
}
if !strings.contains(position_context.import_stmt.fullpath, "/") && !strings.contains(position_context.import_stmt.fullpath, ":") {
-
for key, _ in common.config.collections {
item := CompletionItem {
@@ -1158,7 +1117,6 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte
}
for pkg in search_for_packages(absolute_path) {
-
item := CompletionItem {
detail = pkg,
label = filepath.base(pkg),
@@ -1176,7 +1134,6 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte
}
search_for_packages :: proc(fullpath: string) -> [] string {
-
packages := make([dynamic]string, context.temp_allocator);
fh, err := os.open(fullpath);
@@ -1198,7 +1155,6 @@ search_for_packages :: proc(fullpath: string) -> [] string {
}
get_type_switch_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) {
-
using analysis;
items := make([dynamic]CompletionItem, context.temp_allocator);
@@ -1253,7 +1209,6 @@ get_type_switch_completion :: proc(ast_context: ^analysis.AstContext, position_c
}
get_core_insert_package_if_non_existent :: proc(ast_context: ^analysis.AstContext, pkg: string) -> (TextEdit, bool) {
-
builder := strings.make_builder(context.temp_allocator);
for imp in ast_context.imports {
diff --git a/src/server/definition.odin b/src/server/definition.odin
index 6d44227..01641b4 100644
--- a/src/server/definition.odin
+++ b/src/server/definition.odin
@@ -20,14 +20,13 @@ import "shared:index"
import "shared:analysis"
get_definition_location :: proc(document: ^common.Document, position: common.Position) -> ([]common.Location, bool) {
-
using analysis;
locations := make([dynamic]common.Location, context.temp_allocator);
location: common.Location;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
uri: string;
diff --git a/src/server/document_symbols.odin b/src/server/document_symbols.odin
index 0b4402e..db18e56 100644
--- a/src/server/document_symbols.odin
+++ b/src/server/document_symbols.odin
@@ -21,10 +21,9 @@ import "shared:analysis"
get_document_symbols :: proc(document: ^common.Document) -> []DocumentSymbol {
-
using analysis;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
get_globals(document.ast, &ast_context);
diff --git a/src/server/documents.odin b/src/server/documents.odin
index 2dc1685..71e6cd0 100644
--- a/src/server/documents.odin
+++ b/src/server/documents.odin
@@ -105,11 +105,11 @@ document_open :: proc(uri_string: string, text: string, config: ^common.Config,
return .InvalidRequest;
}
- document.uri = uri;
+ document.uri = uri;
document.client_owned = true;
- document.text = transmute([]u8)text;
- document.used_text = len(document.text);
- document.allocator = document_get_allocator();
+ document.text = transmute([]u8)text;
+ document.used_text = len(document.text);
+ document.allocator = document_get_allocator();
if err := document_refresh(document, config, writer); err != .None {
return err;
@@ -124,6 +124,8 @@ document_open :: proc(uri_string: string, text: string, config: ^common.Config,
allocator = document_get_allocator(),
};
+ document.symbol_cache = make(map[int]rawptr, 10, common.scratch_allocator(document.allocator));
+
if err := document_refresh(&document, config, writer); err != .None {
return err;
}
@@ -248,7 +250,7 @@ document_close :: proc(uri_string: string) -> common.Error {
}
document_refresh :: proc(document: ^common.Document, config: ^common.Config, writer: ^Writer) -> common.Error {
-
+ clear(&document.symbol_cache);
errors, ok := parse_document(document, config);
if !ok {
diff --git a/src/server/hover.odin b/src/server/hover.odin
index 840e666..b77c0b1 100644
--- a/src/server/hover.odin
+++ b/src/server/hover.odin
@@ -60,7 +60,7 @@ get_hover_information :: proc(document: ^common.Document, position: common.Posit
},
};
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
position_context, ok := get_document_position_context(document, position, .Hover);
diff --git a/src/server/inlay_hints.odin b/src/server/inlay_hints.odin
index 7d96c84..e67aac9 100644
--- a/src/server/inlay_hints.odin
+++ b/src/server/inlay_hints.odin
@@ -14,7 +14,7 @@ get_inlay_hints :: proc(document: ^common.Document) -> ([]InlayHint, bool) {
hints := make([dynamic]InlayHint, context.temp_allocator);
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
Visit_Data :: struct {
calls: [dynamic]ast.Call_Expr,
diff --git a/src/server/lens.odin b/src/server/lens.odin
index 9d80d0c..822a115 100644
--- a/src/server/lens.odin
+++ b/src/server/lens.odin
@@ -24,7 +24,7 @@ get_code_lenses :: proc(document: ^common.Document, position: common.Position) -
using analysis;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
get_globals(document.ast, &ast_context);
diff --git a/src/server/requests.odin b/src/server/requests.odin
index fc5ea68..7892432 100644
--- a/src/server/requests.odin
+++ b/src/server/requests.odin
@@ -674,6 +674,8 @@ request_completion :: proc (task: ^common.Task) {
return;
}
+ //context.allocator = common.scratch_allocator(document.allocator);
+
list: CompletionList;
list, ok = get_completion_list(document, completition_params.position, completition_params.context_);
@@ -912,7 +914,6 @@ notification_did_save :: proc (task: ^common.Task) {
warn = index.log_warning_handler,
};
- //have to cheat the parser since it really wants to parse an entire package with the new changes...
dir := filepath.base(filepath.dir(fullpath, context.temp_allocator));
pkg := new(ast.Package);
@@ -937,7 +938,6 @@ notification_did_save :: proc (task: ^common.Task) {
}
for key, value in index.indexer.dynamic_index.collection.symbols {
-
if value.uri == save_params.textDocument.uri {
index.free_symbol(value, context.allocator);
index.indexer.dynamic_index.collection.symbols[key] = {};
diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin
index 40f9020..f7d01dd 100644
--- a/src/server/semantic_tokens.odin
+++ b/src/server/semantic_tokens.odin
@@ -40,7 +40,7 @@ SemanticTokenModifiers :: enum {
}
SemanticTokensClientCapabilities :: struct {
- requests: struct {
+ requests: struct {
range: bool,
},
tokenTypes: []string,
@@ -75,15 +75,11 @@ SemanticTokens :: struct {
}
SemanticTokenBuilder :: struct {
- current_function: ^ast.Node,
- current_start: int,
- selector_member: bool,
- selector_package: bool,
- tokens: [dynamic]u32,
+ current_start: int,
+ tokens: [dynamic]u32,
}
make_token_builder :: proc(allocator := context.temp_allocator) -> SemanticTokenBuilder {
-
return {
tokens = make([dynamic]u32, context.temp_allocator),
};
@@ -95,22 +91,20 @@ get_tokens :: proc(builder: SemanticTokenBuilder) -> SemanticTokens {
};
}
-get_semantic_tokens :: proc(document: ^common.Document, range: common.Range) -> SemanticTokens {
-
+get_semantic_tokens :: proc(document: ^common.Document, range: common.Range) -> SemanticTokens {
using analysis;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, context.temp_allocator);
- builder := make_token_builder();
-
- get_globals(document.ast, &ast_context);
+ builder := make_token_builder();
if document.ast.pkg_decl != nil {
write_semantic_token(&builder, document.ast.pkg_token, document.ast.src, .Keyword, .None);
}
+ resolve_entire_file(document, context.temp_allocator);
+
for decl in document.ast.decls {
if range.start.line <= decl.pos.line && decl.end.line <= range.end.line {
- write_semantic_tokens(decl, &builder, &ast_context);
+
}
}
@@ -118,7 +112,6 @@ 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);
@@ -129,7 +122,6 @@ write_semantic_node :: proc(builder: ^SemanticTokenBuilder, node: ^ast.Node, src
}
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);
@@ -137,8 +129,7 @@ write_semantic_token :: proc(builder: ^SemanticTokenBuilder, token: tokenizer.To
builder.current_start = token.pos.offset;
}
-write_semantic_token_pos :: proc(builder: ^SemanticTokenBuilder, pos: tokenizer.Pos, name: string, src: string, type: SemanticTokenTypes, modifier: SemanticTokenModifiers) {
-
+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);
@@ -146,466 +137,3 @@ write_semantic_token_pos :: proc(builder: ^SemanticTokenBuilder, pos: tokenizer.
builder.current_start = pos.offset;
}
-resolve_and_write_ident :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) -> (is_member: bool, is_package: bool, package_name: string) {
-
- using analysis;
-
- n := node.derived.(ast.Ident);
-
- package_name = ast_context.document_package;
- 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_member = true;
- } else if symbol, ok := resolve_type_identifier(ast_context, n); ok {
- #partial switch v in symbol.value {
- case index.SymbolPackageValue:
- write_semantic_node(builder, node, ast_context.file.src, .Namespace, .None);
- is_package = true;
- package_name = symbol.pkg;
- 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 index.SymbolGenericValue:
- #partial switch symbol.type {
- case .Keyword:
- write_semantic_node(builder, node, ast_context.file.src, .Keyword, .None);
- }
- }
- }
-
- return;
-}
-
-write_semantic_tokens :: proc {
- write_semantic_tokens_node,
- write_semantic_tokens_dynamic_array,
- write_semantic_tokens_array,
- write_semantic_tokens_stmt,
-};
-
-write_semantic_tokens_array :: proc(array: $A/[]^$T, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- for elem, i in array {
- write_semantic_tokens(elem, builder, ast_context);
- }
-}
-
-write_semantic_tokens_dynamic_array :: proc(array: $A/[dynamic]^$T, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- for elem, i in array {
- write_semantic_tokens(elem, builder, ast_context);
- }
-}
-
-write_semantic_tokens_stmt :: proc(node: ^ast.Stmt, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
- ast_context.current_package = ast_context.document_package;
- ast_context.use_globals = true;
- ast_context.use_locals = true;
- builder.selector_member = false;
- write_semantic_tokens_node(node, builder, ast_context);
-}
-
-write_semantic_tokens_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_token_pos(builder, node.pos, "..", ast_context.file.src, .Operator, .None);
- write_semantic_tokens(n.expr, builder, ast_context);
- case Ident:
- 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);
- case Pointer_Type:
- write_semantic_token_pos(builder, node.pos, "^", ast_context.file.src, .Operator, .None);
- write_semantic_tokens(n.elem, builder, ast_context);
- case Value_Decl:
- write_semantic_tokens_value_decl(n, builder, ast_context);
- case Block_Stmt:
- write_semantic_tokens(n.stmts, builder, ast_context);
- case Expr_Stmt:
- write_semantic_tokens(n.expr, builder, ast_context);
- case Range_Stmt:
- write_semantic_token_pos(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_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:
- //could there be any other type then .Function for call expr? No point of computing it if not.
- if ident, ok := n.expr.derived.(Ident); ok {
- write_semantic_node(builder, n.expr, ast_context.file.src, .Function, .None);
- } else {
- 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);
- write_semantic_tokens(n.index, builder, ast_context);
- case Basic_Lit:
- write_semantic_token_basic_lit(n, builder, ast_context);
- case Unary_Expr:
- write_semantic_tokens(n.expr, builder, ast_context);
- case Implicit:
- case Slice_Expr:
- write_semantic_tokens(n.expr, builder, ast_context);
- case Using_Stmt:
- write_semantic_token_pos(builder, n.pos, "using", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.list, builder, ast_context);
- case Map_Type:
- write_semantic_token_pos(builder, n.tok_pos, "map", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(n.key, builder, ast_context);
- write_semantic_tokens(n.value, builder, ast_context);
- case Defer_Stmt:
- write_semantic_token_pos(builder, n.pos, "defer", ast_context.file.src, .Keyword, .None);
- write_semantic_tokens(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);
- }
-}
-
-write_semantic_token_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 {
- }
- }
- }
-}
-
-write_semantic_tokens_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);
- }
-
- write_semantic_tokens(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_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:
- for name in value_decl.names {
- write_semantic_node(builder, name, 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: string) {
-
- 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);
- }
-}
-
-write_semantic_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);
- }
- }
-
- write_semantic_tokens(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);
- }
- }
-
- write_semantic_tokens(result.type, builder, ast_context);
- }
- }
-}
-
-write_semantic_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);
- }
- write_semantic_tokens(f.value, builder, ast_context);
- }
- }
-}
-
-write_semantic_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);
- }
- }
-
- write_semantic_tokens(field.type, builder, ast_context);
- }
-}
-
-write_semantic_selector :: proc(selector: ^ast.Selector_Expr, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) {
-
- using analysis;
- using ast;
-
- if _, ok := selector.expr.derived.(Selector_Expr); !ok {
- get_locals_at(builder.current_function, selector.expr, ast_context);
-
- if symbol, ok := resolve_type_expression(ast_context, selector.expr); ok {
-
- #partial switch v in symbol.value {
- case index.SymbolStructValue:
- builder.selector_member = true;
- }
-
- }
-
- } else {
- write_semantic_tokens(selector.expr, builder, ast_context);
- }
-
- if symbol, ok := resolve_type_expression(ast_context, selector); ok && !builder.selector_member {
-
- #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_member) {
- write_semantic_node(builder, selector.field, ast_context.file.src, .Property, .None);
- }
-}
-
-get_locals_at :: proc(function: ^ast.Node, position: ^ast.Node, ast_context: ^analysis.AstContext) {
-
- using analysis;
-
- clear_locals(ast_context);
-
- if function == nil {
- return;
- }
-
- if position == nil {
- return;
- }
-
- document_position := DocumentPositionContext {
- position = position.end.offset,
- };
-
- get_locals(ast_context.file, function, ast_context, &document_position);
-}
diff --git a/src/server/signature.odin b/src/server/signature.odin
index d7fe289..91e2b47 100644
--- a/src/server/signature.odin
+++ b/src/server/signature.odin
@@ -127,7 +127,7 @@ get_signature_information :: proc(document: ^common.Document, position: common.P
signature_help: SignatureHelp;
- ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
+ ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, &document.symbol_cache);
position_context, ok := get_document_position_context(document, position, .SignatureHelp);