diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2020-11-14 20:40:19 +0100 |
|---|---|---|
| committer | DanielGavin <danielgavin5@hotmail.com> | 2020-11-14 20:40:19 +0100 |
| commit | 556e999c85ecbf9ce0a7d51305bc38c203ffcb00 (patch) | |
| tree | fba239dfad5ba00aa4e8ed69ecb29b11dd616460 /src | |
| parent | 79fdfe53119ac01cb1a1d06609c79aabcac7b946 (diff) | |
indexer and ast works together with foreign packages
Diffstat (limited to 'src')
| -rw-r--r-- | src/index/build.odin | 4 | ||||
| -rw-r--r-- | src/index/clone.odin | 174 | ||||
| -rw-r--r-- | src/index/collector.odin | 302 | ||||
| -rw-r--r-- | src/index/indexer.odin | 5 | ||||
| -rw-r--r-- | src/index/memory_index.odin | 6 | ||||
| -rw-r--r-- | src/index/symbol.odin | 110 | ||||
| -rw-r--r-- | src/server/analysis.odin | 94 | ||||
| -rw-r--r-- | src/server/documents.odin | 2 |
8 files changed, 555 insertions, 142 deletions
diff --git a/src/index/build.odin b/src/index/build.odin index acab4a5..8f3c114 100644 --- a/src/index/build.odin +++ b/src/index/build.odin @@ -19,14 +19,14 @@ import "shared:common" symbol_collection: SymbolCollection; + build_static_index :: proc(allocator := context.allocator, config: ^common.Config) { //right now just collect the symbols from core core_path := config.collections["core"]; - - symbol_collection = make_symbol_collection(allocator); + symbol_collection = make_symbol_collection(allocator, config); walk_static_index_build := proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) { diff --git a/src/index/clone.odin b/src/index/clone.odin new file mode 100644 index 0000000..2354b8a --- /dev/null +++ b/src/index/clone.odin @@ -0,0 +1,174 @@ +package index + +import "core:mem" +import "core:fmt" +import "core:odin/tokenizer" +import "core:odin/ast" +import "core:strings" + +clone_type :: proc{ + clone_node, + clone_expr, + clone_array, + clone_dynamic_array, +}; + +clone_array :: proc(array: $A/[]^$T, allocator := context.allocator) -> A { + if len(array) == 0 { + return nil; + } + res := make(A, len(array)); + for elem, i in array { + res[i] = auto_cast clone_type(elem, allocator); + } + return res; +} + +clone_dynamic_array :: proc(array: $A/[dynamic]^$T, allocator := context.allocator) -> A { + if len(array) == 0 { + return nil; + } + res := make(A, len(array)); + for elem, i in array { + res[i] = auto_cast clone_type(elem, allocator); + } + return res; +} + +clone_expr :: proc(node: ^ast.Expr, allocator := context.allocator) -> ^ast.Expr { + return cast(^ast.Expr)clone_node(node, allocator); +} + +clone_node :: proc(node: ^ast.Node, allocator := context.allocator) -> ^ast.Node { + + using ast; + + if node == nil { + return nil; + } + + size := size_of(Node); + align := align_of(Node); + ti := type_info_of(node.derived.id); + if ti != nil { + size = ti.size; + align = ti.align; + } + + res := cast(^Node)mem.alloc(size, align, allocator); + src: rawptr = node; + if node.derived != nil { + src = node.derived.data; + } + mem.copy(res, src, size); + res.derived.data = rawptr(res); + + switch n in node.derived { + case Bad_Expr: + case Ident: + r := cast(^Ident)res; + r.name = strings.clone(n.name, allocator); + case Implicit: + case Undef: + case Basic_Lit: + + case Ellipsis: + r := cast(^Ellipsis)res; + r.expr = clone_type(r.expr, allocator); + case Tag_Expr: + r := cast(^Tag_Expr)res; + r.expr = clone_type(r.expr, allocator); + case Unary_Expr: + r := cast(^Unary_Expr)res; + r.expr = clone_type(r.expr, allocator); + case Binary_Expr: + r := cast(^Binary_Expr)res; + r.left = clone_type(r.left, allocator); + r.right = clone_type(r.right, allocator); + case Paren_Expr: + r := cast(^Paren_Expr)res; + r.expr = clone_type(r.expr, allocator); + case Selector_Expr: + r := cast(^Selector_Expr)res; + r.expr = clone_type(r.expr, allocator); + r.field = auto_cast clone_type(r.field, allocator); + case Slice_Expr: + r := cast(^Slice_Expr)res; + r.expr = clone_type(r.expr, allocator); + r.low = clone_type(r.low, allocator); + r.high = clone_type(r.high, allocator); + case Attribute: + r := cast(^Attribute)res; + r.elems = clone_type(r.elems, allocator); + case Distinct_Type: + r := cast(^Distinct_Type)res; + r.type = clone_type(r.type, allocator); + case Opaque_Type: + r := cast(^Opaque_Type)res; + r.type = clone_type(r.type, allocator); + case Proc_Type: + r := cast(^Proc_Type)res; + r.params = auto_cast clone_type(r.params, allocator); + r.results = auto_cast clone_type(r.results, allocator); + case Pointer_Type: + r := cast(^Pointer_Type)res; + r.elem = clone_type(r.elem, allocator); + case Array_Type: + r := cast(^Array_Type)res; + r.len = clone_type(r.len, allocator); + r.elem = clone_type(r.elem, allocator); + case Dynamic_Array_Type: + r := cast(^Dynamic_Array_Type)res; + r.elem = clone_type(r.elem, allocator); + case Struct_Type: + r := cast(^Struct_Type)res; + r.poly_params = auto_cast clone_type(r.poly_params, allocator); + r.align = clone_type(r.align, allocator); + r.fields = auto_cast clone_type(r.fields, allocator); + case Field: + r := cast(^Field)res; + r.names = clone_type(r.names, allocator); + r.type = clone_type(r.type, allocator); + r.default_value = clone_type(r.default_value, allocator); + case Field_List: + r := cast(^Field_List)res; + r.list = clone_type(r.list, allocator); + case Field_Value: + r := cast(^Field_Value)res; + r.field = clone_type(r.field, allocator); + r.value = clone_type(r.value, allocator); + case Union_Type: + r := cast(^Union_Type)res; + r.poly_params = auto_cast clone_type(r.poly_params, allocator); + r.align = clone_type(r.align, allocator); + r.variants = clone_type(r.variants, allocator); + case Enum_Type: + r := cast(^Enum_Type)res; + r.base_type = clone_type(r.base_type, allocator); + r.fields = clone_type(r.fields, allocator); + case Bit_Field_Type: + r := cast(^Bit_Field_Type)res; + r.fields = clone_type(r.fields, allocator); + case Bit_Set_Type: + r := cast(^Bit_Set_Type)res; + r.elem = clone_type(r.elem, allocator); + r.underlying = clone_type(r.underlying, allocator); + case Map_Type: + r := cast(^Map_Type)res; + r.key = clone_type(r.key, allocator); + r.value = clone_type(r.value, allocator); + case Call_Expr: + r := cast(^Call_Expr)res; + r.expr = clone_type(r.expr, allocator); + r.args = clone_type(r.args, allocator); + case Typeid_Type: + r := cast(^Typeid_Type)res; + r.specialization = clone_type(r.specialization, allocator); + case: + fmt.panicf("Unhandled node kind: %T", n); + } + + return res; +} + + diff --git a/src/index/collector.odin b/src/index/collector.odin new file mode 100644 index 0000000..68691dd --- /dev/null +++ b/src/index/collector.odin @@ -0,0 +1,302 @@ +package index + +import "core:odin/ast" +import "core:hash" +import "core:strings" +import "core:mem" +import "core:fmt" +import "core:path/filepath" +import "core:path" + +import "shared:common" + + +SymbolCollection :: struct { + allocator: mem.Allocator, + config: ^common.Config, + symbols: map[string] Symbol, + unique_strings: map[string] string, //store all our strings as unique strings and reference them to save memory. +}; + + +get_index_unique_string :: proc(collection: ^SymbolCollection, s: string) -> string { + + //i'm hashing this string way to much + if _, ok := collection.unique_strings[s]; !ok { + collection.unique_strings[s] = strings.clone(s, collection.allocator); + } + + return collection.unique_strings[s]; +} + + +make_symbol_collection :: proc(allocator := context.allocator, config: ^common.Config) -> SymbolCollection { + return SymbolCollection { + allocator = allocator, + config = config, + symbols = make(map[string] Symbol, 16, allocator), + unique_strings = make(map[string] string, 16, allocator), + }; +} + +collect_struct_fields :: proc(collection: ^SymbolCollection, fields: ^ast.Field_List, package_map: map [string] string) -> SymbolStructValue { + + names := make([dynamic] string, 0, collection.allocator); + types := make([dynamic] ^ast.Expr, 0, collection.allocator); + + for field in fields.list { + + for n in field.names { + identifier := n.derived.(ast.Ident); + append(&names, get_index_unique_string(collection, identifier.name)); + append(&types, clone_type(field.type, collection.allocator)); + } + + } + + for t in types { + replace_package_alias(t, package_map, collection); + } + + value := SymbolStructValue { + names = names[:], + types = types[:], + }; + + return value; +} + + + +collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: string) -> common.Error { + + forward, _ := filepath.to_slash(file.fullpath, context.temp_allocator); + directory := path.dir(forward, context.temp_allocator); + package_map := get_package_mapping(file, collection.config); + + for decl in file.decls { + + symbol: Symbol; + + if value_decl, ok := decl.derived.(ast.Value_Decl); ok { + + name := string(file.src[value_decl.names[0].pos.offset:value_decl.names[0].end.offset]); + + if len(value_decl.values) == 1 { + + token: ast.Node; + token_type: SymbolType; + + switch v in value_decl.values[0].derived { + case ast.Proc_Lit: + token = v; + token_type = .Function; + + if v.type.params != nil { + symbol.signature = get_index_unique_string(collection, + strings.concatenate( {"(", string(file.src[v.type.params.pos.offset:v.type.params.end.offset]), ")"}, + context.temp_allocator)); + } + case ast.Struct_Type: + token = v; + token_type = .Struct; + symbol.value = collect_struct_fields(collection, v.fields, package_map); + case: // default + break; + } + + symbol.range = common.get_token_range(token, file.src); + symbol.name = get_index_unique_string(collection, name); + symbol.scope = get_index_unique_string(collection, directory); + symbol.type = token_type; + symbol.uri = get_index_unique_string(collection, uri); + + //id := hash.murmur64(transmute([]u8)strings.concatenate({symbol.scope, name}, context.temp_allocator)); + + collection.symbols[strings.concatenate({symbol.scope, name}, context.temp_allocator)] = symbol; + } + + } + } + + return .None; +} + + +/* + Gets the map from import alias to absolute package directory +*/ +get_package_mapping :: proc(file: ast.File, config: ^common.Config) -> map [string] string { + + package_map := make(map [string] string, 0, context.temp_allocator); + + for imp, index in file.imports { + + //collection specified + if i := strings.index(imp.fullpath, ":"); i != -1 { + + collection := imp.fullpath[1:i]; + p := imp.fullpath[i+1:len(imp.fullpath)-1]; + + dir, ok := config.collections[collection]; + + if !ok { + continue; + } + + name: string; + + full := path.join(elems = {dir, p}, allocator = context.temp_allocator); + + if imp.name.text != "" { + name = imp.name.text; + } + + else { + name = path.base(full, false, context.temp_allocator); + } + + package_map[name] = full; + + } + + else { + + } + + } + + + return package_map; +} + + +/* + We can't have the alias names for packages with selector expression since that is specific to every files import, instead just replace it with the absolute + package name(absolute directory path) +*/ + +replace_package_alias :: proc{ + replace_package_alias_node, + replace_package_alias_expr, + replace_package_alias_array, + replace_package_alias_dynamic_array, +}; + +replace_package_alias_array :: proc(array: $A/[]^$T, package_map: map [string] string, collection: ^SymbolCollection) { + + for elem, i in array { + replace_package_alias(elem, package_map, collection); + } + +} + +replace_package_alias_dynamic_array :: proc(array: $A/[dynamic]^$T, package_map: map [string] string, collection: ^SymbolCollection) { + + for elem, i in array { + replace_package_alias(elem, package_map, collection); + } + +} + +replace_package_alias_expr :: proc(node: ^ast.Expr, package_map: map [string] string, collection: ^SymbolCollection) { + replace_package_alias_node(node, package_map, collection); +} + +replace_package_alias_node :: proc(node: ^ast.Node, package_map: map [string] string, collection: ^SymbolCollection) { + + using ast; + + if node == nil { + return; + } + + switch n in node.derived { + case Bad_Expr: + case Ident: + case Implicit: + case Undef: + case Basic_Lit: + case Ellipsis: + replace_package_alias(n.expr, package_map, collection); + case Tag_Expr: + replace_package_alias(n.expr, package_map, collection); + case Unary_Expr: + replace_package_alias(n.expr, package_map, collection); + case Binary_Expr: + replace_package_alias(n.left, package_map, collection); + replace_package_alias(n.right, package_map, collection); + case Paren_Expr: + replace_package_alias(n.expr, package_map, collection); + case Selector_Expr: + + if ident := &n.expr.derived.(Ident); ident != nil { + + if package_name, ok := package_map[ident.name]; ok { + ident.name = get_index_unique_string(collection, package_name); + } + + } + + else { + replace_package_alias(n.expr, package_map, collection); + replace_package_alias(n.field, package_map, collection); + } + case Slice_Expr: + replace_package_alias(n.expr, package_map, collection); + replace_package_alias(n.low, package_map, collection); + replace_package_alias(n.high, package_map, collection); + case Attribute: + replace_package_alias(n.elems, package_map, collection); + case Distinct_Type: + replace_package_alias(n.type, package_map, collection); + case Opaque_Type: + replace_package_alias(n.type, package_map, collection); + case Proc_Type: + replace_package_alias(n.params, package_map, collection); + replace_package_alias(n.results, package_map, collection); + case Pointer_Type: + replace_package_alias(n.elem, package_map, collection); + case Array_Type: + replace_package_alias(n.len, package_map, collection); + replace_package_alias(n.elem, package_map, collection); + case Dynamic_Array_Type: + replace_package_alias(n.elem, package_map, collection); + case Struct_Type: + replace_package_alias(n.poly_params, package_map, collection); + replace_package_alias(n.align, package_map, collection); + replace_package_alias(n.fields, package_map, collection); + case Field: + replace_package_alias(n.names, package_map, collection); + replace_package_alias(n.type, package_map, collection); + replace_package_alias(n.default_value, package_map, collection); + case Field_List: + replace_package_alias(n.list, package_map, collection); + case Field_Value: + replace_package_alias(n.field, package_map, collection); + replace_package_alias(n.value, package_map, collection); + case Union_Type: + replace_package_alias(n.poly_params, package_map, collection); + replace_package_alias(n.align, package_map, collection); + replace_package_alias(n.variants, package_map, collection); + case Enum_Type: + replace_package_alias(n.base_type, package_map, collection); + replace_package_alias(n.fields, package_map, collection); + case Bit_Field_Type: + replace_package_alias(n.fields, package_map, collection); + case Bit_Set_Type: + replace_package_alias(n.elem, package_map, collection); + replace_package_alias(n.underlying, package_map, collection); + case Map_Type: + replace_package_alias(n.key, package_map, collection); + replace_package_alias(n.value, package_map, collection); + case Call_Expr: + replace_package_alias(n.expr, package_map, collection); + replace_package_alias(n.args, package_map, collection); + case Typeid_Type: + replace_package_alias(n.specialization, package_map, collection); + case: + fmt.panicf("Unhandled node kind: %T", n); + } + +}
\ No newline at end of file diff --git a/src/index/indexer.odin b/src/index/indexer.odin index 235303d..88e5419 100644 --- a/src/index/indexer.odin +++ b/src/index/indexer.odin @@ -3,6 +3,7 @@ package index import "core:odin/ast" import "core:fmt" import "core:strings" +import "core:log" /* @@ -44,7 +45,9 @@ indexer: Indexer; lookup :: proc(name: string, scope: string) -> (Symbol, bool) { - return memory_index_lookup(&indexer.static_index, name, scope); + symbol, ok := memory_index_lookup(&indexer.static_index, name, scope); + //log.infof("lookup name: %v scope: %v, symbol %v", name, scope, symbol); + return symbol, ok; } diff --git a/src/index/memory_index.odin b/src/index/memory_index.odin index e9c0135..c3b38bf 100644 --- a/src/index/memory_index.odin +++ b/src/index/memory_index.odin @@ -26,10 +26,8 @@ make_memory_index :: proc(collection: SymbolCollection) -> MemoryIndex { } memory_index_lookup :: proc(index: ^MemoryIndex, name: string, scope: string) -> (Symbol, bool) { - - hashed := hash.murmur64(transmute([]u8)strings.concatenate({scope, name}, context.temp_allocator)); - - return index.collection.symbols[hashed]; + //hashed := hash.murmur64(transmute([]u8)strings.concatenate({scope, name}, context.temp_allocator)); + return index.collection.symbols[strings.concatenate({scope, name}, context.temp_allocator)]; } memory_index_fuzzy_search :: proc(index: ^MemoryIndex, name: string, scope: [] string) -> ([] Symbol, bool) { diff --git a/src/index/symbol.odin b/src/index/symbol.odin index 0906e74..46624d5 100644 --- a/src/index/symbol.odin +++ b/src/index/symbol.odin @@ -16,6 +16,12 @@ import "shared:common" */ + +SymbolFile :: struct { + imports: [] string, +}; + + SymbolStructValue :: struct { names: [] string, types: [] ^ast.Expr, @@ -38,6 +44,7 @@ Symbol :: struct { signature: string, type: SymbolType, value: SymbolValue, + file: ^SymbolFile, }; SymbolType :: enum { @@ -46,105 +53,4 @@ SymbolType :: enum { Package = 9, //set by ast symbol Keyword = 14, //set by ast symbol Struct = 22, -}; - -SymbolCollection :: struct { - allocator: mem.Allocator, - symbols: map[u64] Symbol, - unique_strings: map[u64] string, //store all our strings as unique strings and reference them to save memory. -}; - -get_index_unique_string :: proc(collection: ^SymbolCollection, s: string) -> string { - - id := hash.murmur64(transmute([]u8)s); - - if _, ok := collection.unique_strings[id]; !ok { - collection.unique_strings[id] = strings.clone(s, collection.allocator); - } - - return collection.unique_strings[id]; -} - -make_symbol_collection :: proc(allocator := context.allocator) -> SymbolCollection { - return SymbolCollection { - allocator = allocator, - symbols = make(map[u64] Symbol, 16, allocator), - unique_strings = make(map[u64] string, 16, allocator), - }; -} - -collect_struct_fields :: proc(collection: ^SymbolCollection, fields: ^ast.Field_List, src: [] byte) -> SymbolStructValue { - - names := make([dynamic] string, 0, collection.allocator); - types := make([dynamic] ^ast.Expr, 0, collection.allocator); - - for field in fields.list { - - for n in field.names { - identifier := n.derived.(ast.Ident); - append(&names, get_index_unique_string(collection, identifier.name)); - append(&types, ast.clone_expr(field.type)); - } - - } - - value := SymbolStructValue { - names = names[:], - types = types[:], - }; - - return value; -} - -collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: string) -> common.Error { - - forward, _ := filepath.to_slash(file.fullpath, context.temp_allocator); - directory := path.dir(forward, context.temp_allocator); - - for decl in file.decls { - - symbol: Symbol; - - if value_decl, ok := decl.derived.(ast.Value_Decl); ok { - - name := string(file.src[value_decl.names[0].pos.offset:value_decl.names[0].end.offset]); - - if len(value_decl.values) == 1 { - - token: ast.Node; - token_type: SymbolType; - - switch v in value_decl.values[0].derived { - case ast.Proc_Lit: - token = v; - token_type = .Function; - - if v.type.params != nil { - symbol.signature = get_index_unique_string(collection, - strings.concatenate( {"(", string(file.src[v.type.params.pos.offset:v.type.params.end.offset]), ")"}, - context.temp_allocator)); - } - case ast.Struct_Type: - token = v; - token_type = .Struct; - symbol.value = collect_struct_fields(collection, v.fields, file.src); - case: // default - break; - } - - symbol.range = common.get_token_range(token, file.src); - symbol.name = get_index_unique_string(collection, name); - symbol.scope = get_index_unique_string(collection, directory); - symbol.type = token_type; - symbol.uri = get_index_unique_string(collection, uri); - - id := hash.murmur64(transmute([]u8)strings.concatenate({symbol.scope, name}, context.temp_allocator)); - - collection.symbols[id] = symbol; - } - - } - } - - return .None; -} +};
\ No newline at end of file diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 1bef7f4..b23b6d8 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -35,17 +35,24 @@ AstContext :: struct { globals: map [string] ^ast.Expr, file: ast.File, allocator: mem.Allocator, - imports: [] Package, - foreign_package: bool, + imports: [] Package, //imports for the current document + current_package: string, + document_package: string, + use_globals: bool, + use_locals: bool, }; -make_ast_context :: proc(file: ast.File, imports: [] Package, allocator := context.temp_allocator) -> AstContext { +make_ast_context :: proc(file: ast.File, imports: [] Package, package_name: string, allocator := context.temp_allocator) -> AstContext { ast_context := AstContext { locals = make(map [string] ^ast.Expr, 0, allocator), globals = make(map [string] ^ast.Expr, 0, allocator), file = file, imports = imports, + use_locals = true, + use_globals = true, + document_package = package_name, + current_package = package_name, }; return ast_context; @@ -68,21 +75,30 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr, expec if selector, ok := resolve_type_expression(ast_context, v.expr); ok { + ast_context.use_locals = false; + switch s in selector.value { case index.SymbolStructValue: + + if selector.uri != "" { + ast_context.current_package = selector.scope; + } + for name, i in s.names { if v.field != nil && strings.compare(name, v.field.name) == 0 { return resolve_type_expression(ast_context, s.types[i], false); } } case index.SymbolPackageValue: - //TODO(Daniel, when we go into a package we are no longer in our project and cannot look at globals and locals) + + ast_context.current_package = selector.scope; + if v.field != nil { - //ast_context.foreign_package = true; return index.lookup(v.field.name, selector.scope); } else { + log.error("No field"); return index.Symbol {}, false; } @@ -107,9 +123,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, expec using ast; - log.info(node.name); - - if local, ok := ast_context.locals[node.name]; !ast_context.foreign_package && ok { + if local, ok := ast_context.locals[node.name]; ast_context.use_locals && ok { switch v in local.derived { case Ident: @@ -136,7 +150,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, expec } } - else if global, ok := ast_context.globals[node.name]; !ast_context.foreign_package && ok { + else if global, ok := ast_context.globals[node.name]; ast_context.use_globals && ok { switch v in global.derived { case Ident: @@ -164,7 +178,9 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, expec } //keywords - else if node.name == "int" || node.name == "string" { + else if node.name == "int" || node.name == "string" + || node.name == "u64" || node.name == "f32" + || node.name == "i64" || node.name == "i32" { symbol := index.Symbol { type = .Keyword, @@ -176,25 +192,43 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, expec //imports - probably have this higher to check imports befure everything else else { - for imp in ast_context.imports { - - if strings.compare(imp.base, node.name) == 0 { + //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 { + symbol := index.Symbol { type = .Package, - scope = imp.name, + scope = node.name, value = index.SymbolPackageValue { } }; - return symbol, true; + return symbol, true; + + } + + else { + + 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; + } + } } //last option is to check the index - + return index.lookup(node.name, ast_context.current_package); //TODO(daniel, index can be used on identifiers if using is in the function scope) @@ -329,7 +363,7 @@ get_definition_location :: proc(document: ^Document, position: common.Position) location: common.Location; - ast_context := make_ast_context(document.ast, document.imports); + ast_context := make_ast_context(document.ast, document.imports, document.package_name); uri: string; @@ -387,7 +421,6 @@ get_definition_location :: proc(document: ^Document, position: common.Position) } case index.SymbolPackageValue: if symbol, ok := index.lookup(field, selector.scope); ok { - log.info(symbol); location.range = symbol.range; uri = symbol.uri; } @@ -424,7 +457,7 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> ( list: CompletionList; - ast_context := make_ast_context(document.ast, document.imports); + ast_context := make_ast_context(document.ast, document.imports, document.package_name); position_context, ok := get_document_position_context(document, position, .Completion); @@ -449,6 +482,10 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> ( } + if selector.uri != "" { + ast_context.current_package = selector.scope; + } + field: string; if position_context.field != nil { @@ -480,6 +517,8 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> ( list.isIncomplete = false; case index.SymbolPackageValue: + list.isIncomplete = true; + if field != "" { if searched, ok := index.fuzzy_search(selector.name, {selector.scope}); ok { @@ -491,12 +530,11 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> ( } else { + log.errorf("Failed to fuzzy search, field: %v, package: %v", field, selector.scope); return list, true; } } - - list.isIncomplete = true; } } @@ -512,8 +550,6 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> ( list.items[i].kind = cast(CompletionItemKind) symbol.type; } - log.info(list); - return list, true; } @@ -521,7 +557,7 @@ get_signature_information :: proc(document: ^Document, position: common.Position signature_help: SignatureHelp; - ast_context := make_ast_context(document.ast, document.imports); + ast_context := make_ast_context(document.ast, document.imports, document.package_name); position_context, ok := get_document_position_context(document, position, .SignatureHelp); @@ -542,8 +578,6 @@ get_signature_information :: proc(document: ^Document, position: common.Position call: index.Symbol; call, ok = resolve_type_expression(&ast_context, position_context.call); - log.info(call); - signature_information := make([] SignatureInformation, 1, context.temp_allocator); signature_information[0].label = strings.concatenate({call.name, call.signature}, context.temp_allocator); @@ -632,11 +666,7 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP //do we still have recursive dots? if strings.contains(string(str), ".") { - log.info(common.get_ast_node_string(node, position_context.file.src)); - log.info(n.derived); - e := parser.parse_expr(&p, true); //MEMORY LEAK - need to modify parser to allow for temp allocator - position_context.selector = e; } @@ -670,10 +700,8 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP case Tag_Expr: get_document_position(n.expr, position_context); case Unary_Expr: - log.info("%v", n.op.text); get_document_position(n.expr, position_context); case Binary_Expr: - log.info("%v", n.op.text); get_document_position(n.left, position_context); get_document_position(n.right, position_context); case Paren_Expr: diff --git a/src/server/documents.odin b/src/server/documents.odin index a626ec3..689e1c0 100644 --- a/src/server/documents.odin +++ b/src/server/documents.odin @@ -33,6 +33,7 @@ Document :: struct { diagnosed_errors: bool, ast: ast.File, imports: [] Package, + package_name: string, }; DocumentStorage :: struct { @@ -346,6 +347,7 @@ parse_document :: proc(document: ^Document, config: ^common.Config) -> ([] Parse } document.imports = make([]Package, len(document.ast.imports)); + document.package_name = path.dir(document.uri.path, context.allocator); //todo(memory leak) for imp, index in document.ast.imports { |