diff options
| author | Daniel Gavin <danielgavin5@hotmail.com> | 2022-06-11 11:46:14 +0200 |
|---|---|---|
| committer | Daniel Gavin <danielgavin5@hotmail.com> | 2022-06-11 11:46:14 +0200 |
| commit | 70d5bcf8eca474440020c31239cd827cf3bb3415 (patch) | |
| tree | 3fec51ed6f3257ad73b971e98dcb7c6b5e1f68fc /src/server | |
| parent | eda3110541a5a9f6f5e3b9428139f5d060e6a3ae (diff) | |
More reference work
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/analysis.odin | 155 | ||||
| -rw-r--r-- | src/server/build.odin | 83 | ||||
| -rw-r--r-- | src/server/caches.odin | 1 | ||||
| -rw-r--r-- | src/server/collector.odin | 53 | ||||
| -rw-r--r-- | src/server/completion.odin | 21 | ||||
| -rw-r--r-- | src/server/documents.odin | 33 | ||||
| -rw-r--r-- | src/server/indexer.odin | 3 | ||||
| -rw-r--r-- | src/server/reader.odin | 2 | ||||
| -rw-r--r-- | src/server/references.odin | 35 | ||||
| -rw-r--r-- | src/server/requests.odin | 5 | ||||
| -rw-r--r-- | src/server/signature.odin | 8 | ||||
| -rw-r--r-- | src/server/symbol.odin | 1 | ||||
| -rw-r--r-- | src/server/types.odin | 1 |
13 files changed, 241 insertions, 160 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 34dcc5f..a4ec13b 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -840,8 +840,9 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (S ast_context.current_package = saved_package } - if ast_context.recursion_counter > 15 { - log.error("Recursion passed 15 attempts - giving up") + if ast_context.recursion_counter > 200 { + log.error("Recursion passed 200 attempts - giving up", node) + assert(false) return {}, false } @@ -1122,8 +1123,9 @@ get_local_offset :: proc(ast_context: ^AstContext, offset: int, name: string) -> resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (Symbol, bool) { using ast - if ast_context.recursion_counter > 15 { - log.error("Recursion passed 15 attempts - giving up") + if ast_context.recursion_counter > 200 { + log.error("Recursion passed 200 attempts - giving up", node) + assert(false) return {}, false } @@ -1143,7 +1145,37 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (S ast_context.current_package = pkg } - if _, ok := ast_context.parameters[node.name]; ok { + if v, ok := common.keyword_map[node.name]; ok { + //keywords + ident := new_type(Ident, node.pos, node.end, ast_context.allocator) + ident.name = node.name + + symbol: Symbol + + switch ident.name { + case "true", "false": + symbol = Symbol { + type = .Keyword, + signature = node.name, + pkg = ast_context.current_package, + value = SymbolUntypedValue { + type = .Bool, + }, + } + case: + symbol = Symbol { + type = .Keyword, + signature = node.name, + name = ident.name, + pkg = ast_context.current_package, + value = SymbolBasicValue { + ident = ident, + }, + } + } + + return symbol, true + } else if _, ok := ast_context.parameters[node.name]; ok { for imp in ast_context.imports { if strings.compare(imp.base, node.name) == 0 { symbol := Symbol { @@ -1155,9 +1187,8 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (S return symbol, true } } - } - - //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 @@ -1173,6 +1204,9 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (S #partial switch v in local.derived { case ^Ident: + if v.name == node.name { + return {}, false + } return_symbol, ok = resolve_type_identifier(ast_context, v^) case ^Union_Type: return_symbol, ok = make_symbol_union_from_ast(ast_context, v^, node.name), true @@ -1220,6 +1254,8 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (S return_symbol.type = .Variable } + return_symbol.flags |= {.Local} + return return_symbol, ok } else if global, ok := ast_context.globals[node.name]; ast_context.use_globals && ok { @@ -1237,6 +1273,9 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (S #partial switch v in global.expr.derived { case ^Ident: + if v.name == node.name { + return {}, false + } return_symbol, ok = resolve_type_identifier(ast_context, v^) case ^Struct_Type: return_symbol, ok = make_symbol_struct_from_ast(ast_context, v^, node.name), true @@ -1293,36 +1332,6 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (S return symbol, ok } } - } else if v, ok := common.keyword_map[node.name]; ok { - //keywords - ident := new_type(Ident, node.pos, node.end, ast_context.allocator) - ident.name = node.name - - symbol: Symbol - - switch ident.name { - case "true", "false": - symbol = Symbol { - type = .Keyword, - signature = node.name, - pkg = ast_context.current_package, - value = SymbolUntypedValue { - type = .Bool, - }, - } - case: - symbol = Symbol { - type = .Keyword, - signature = node.name, - name = ident.name, - pkg = ast_context.current_package, - value = SymbolBasicValue { - ident = ident, - }, - } - } - - return symbol, true } 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, "/") { @@ -1850,10 +1859,12 @@ make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type for field in v.fields.list { for n in field.names { - if identifier, ok := n.derived.(^ast.Ident); ok { + if identifier, ok := n.derived.(^ast.Ident); ok && field.type != nil { + if identifier.name == "_" { + continue + } append(&names, identifier.name) append(&types, clone_type(field.type, ast_context.allocator, nil)) - if .Using in field.flags { usings[identifier.name] = true } @@ -2233,9 +2244,11 @@ get_locals_for_range_stmt :: proc(file: ast.File, stmt: ast.Range_Stmt, ast_cont if binary, ok := stmt.expr.derived.(^ast.Binary_Expr); ok { if binary.op.kind == .Range_Half { - if ident, ok := stmt.vals[0].derived.(^Ident); ok { - store_local(ast_context, make_int_ast(ast_context), ident.pos.offset, ident.name, ast_context.local_id) - ast_context.variables[ident.name] = true + if len(stmt.vals) >= 1 { + if ident, ok := stmt.vals[0].derived.(^Ident); ok { + store_local(ast_context, make_int_ast(ast_context), ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true + } } } } @@ -2431,7 +2444,7 @@ clear_locals :: proc(ast_context: ^AstContext) { clear(&ast_context.usings) } -resolve_entire_file :: proc(document: ^common.Document, allocator := context.allocator) -> map[uintptr]SymbolAndNode { +resolve_entire_file :: proc(document: ^common.Document, skip_locals := false, allocator := context.allocator) -> map[uintptr]SymbolAndNode { ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, allocator) get_globals(document.ast, &ast_context) @@ -2441,14 +2454,14 @@ resolve_entire_file :: proc(document: ^common.Document, allocator := context.all symbols := make(map[uintptr]SymbolAndNode, 10000, allocator) for decl in document.ast.decls { - resolve_entire_decl(&ast_context, decl, &symbols, allocator) + resolve_entire_decl(&ast_context, decl, &symbols, skip_locals, allocator) clear(&ast_context.locals) } return symbols } -resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Node, symbols: ^map[uintptr]SymbolAndNode, allocator := context.allocator) { +resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Node, symbols: ^map[uintptr]SymbolAndNode, skip_locals := false, allocator := context.allocator) { Scope :: struct { offset: int, id: int, @@ -2459,12 +2472,15 @@ resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Node, symbols: symbols: ^map[uintptr]SymbolAndNode, scopes: [dynamic]Scope, id_counter: int, + last_visit: ^ast.Node, + skip_locals: bool, } data := Visit_Data { ast_context = ast_context, symbols = symbols, scopes = make([dynamic]Scope, allocator), + skip_locals = skip_locals, } visit :: proc(visitor: ^ast.Visitor, node: ^ast.Node) -> ^ast.Visitor { @@ -2476,6 +2492,8 @@ resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Node, symbols: ast_context.use_locals = true ast_context.use_globals = true + data.last_visit = node; + //It's somewhat silly to check the scope everytime, but the alternative is to implement my own walker function. if len(data.scopes) > 0 { current_scope := data.scopes[len(data.scopes)-1] @@ -2494,8 +2512,12 @@ resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Node, symbols: } } - #partial switch v in node.derived { - case ^ast.If_Stmt, ^ast.For_Stmt, ^ast.Range_Stmt, ^ast.Inline_Range_Stmt, ^ast.Proc_Lit: + #partial done: switch v in node.derived { + case ^ast.Proc_Lit: + if v.body == nil { + break + } + scope: Scope scope.id = data.id_counter scope.offset = node.end.offset @@ -2507,16 +2529,37 @@ resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Node, symbols: position_context: DocumentPositionContext position_context.position = node.end.offset + + get_locals_proc_param_and_results(ast_context.file, v^, ast_context, &position_context) get_locals_stmt(ast_context.file, cast(^ast.Stmt)node, ast_context, &position_context) - case ^ast.Ident: + case ^ast.If_Stmt, ^ast.For_Stmt, ^ast.Range_Stmt, ^ast.Inline_Range_Stmt: + scope: Scope + scope.id = data.id_counter + scope.offset = node.end.offset + data.id_counter += 1 + ast_context.local_id = scope.id + + append(&data.scopes, scope) + add_local_group(ast_context, scope.id) + + position_context: DocumentPositionContext + position_context.position = node.end.offset + get_locals_stmt(ast_context.file, cast(^ast.Stmt)node, ast_context, &position_context) + case ^ast.Ident: if symbol, ok := resolve_type_identifier(ast_context, v^); ok { + if .Local in symbol.flags && data.skip_locals { + break done + } data.symbols[cast(uintptr)node] = SymbolAndNode { node = v, symbol = symbol, } - } + } case ^ast.Selector_Expr: if symbol, ok := resolve_type_expression(ast_context, &v.node); ok { + if .Local in symbol.flags && data.skip_locals { + break done + } data.symbols[cast(uintptr)node] = SymbolAndNode { node = v, symbol = symbol, @@ -2531,17 +2574,6 @@ resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Node, symbols: } } - #partial switch v in node.derived { - case ^ast.Proc_Lit: - if v.body == nil { - break - } - - type_position_context: DocumentPositionContext - type_position_context.position = v.end.offset - get_locals_proc_param_and_results(ast_context.file, v^, ast_context, &type_position_context) - } - return visitor } @@ -2584,7 +2616,6 @@ unwrap_enum :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (SymbolEnumVal } if enum_symbol, ok := resolve_type_expression(ast_context, node); ok { - if enum_value, ok := enum_symbol.value.(SymbolEnumValue); ok { return enum_value, true } diff --git a/src/server/build.odin b/src/server/build.odin index 5850361..ad186be 100644 --- a/src/server/build.odin +++ b/src/server/build.odin @@ -141,57 +141,64 @@ build_static_index :: proc(allocator := context.allocator, config: ^common.Confi free_all(context.allocator) } - //afterwards, I have to go through the files again to find all the references. Better to reload individually the files again to ensure we don't use too much memory. - - for fullpath in files { - data, ok := os.read_entire_file(fullpath, context.allocator) + indexer.static_index = make_memory_index(symbol_collection) - if !ok { - log.errorf("failed to read entire file for indexing %v", fullpath) - continue - } + if config.enable_references { + for fullpath in files { + data, ok := os.read_entire_file(fullpath, context.allocator) - p := parser.Parser { - err = log_error_handler, - warn = log_warning_handler, - flags = {.Optional_Semicolons}, - } + if !ok { + log.errorf("failed to read entire file for indexing %v", fullpath) + continue + } - dir := filepath.base(filepath.dir(fullpath, context.allocator)) + //TODO(daniel): Implement path code to handle whether paths are contained in core + if !config.enable_std_references && (strings.contains(fullpath, "Odin/core") || strings.contains(fullpath, "odin/core")) { + continue; + } - pkg := new(ast.Package) - pkg.kind = .Normal - pkg.fullpath = fullpath - pkg.name = dir + p := parser.Parser { + err = log_error_handler, + warn = log_warning_handler, + flags = {.Optional_Semicolons}, + } - if dir == "runtime" { - pkg.kind = .Runtime - } + dir := filepath.base(filepath.dir(fullpath, context.allocator)) - file := ast.File { - fullpath = fullpath, - src = string(data), - pkg = pkg, - } + pkg := new(ast.Package) + pkg.kind = .Normal + pkg.fullpath = fullpath + pkg.name = dir - ok = parser.parse_file(&p, &file) + if dir == "runtime" { + pkg.kind = .Runtime + } - if !ok { - log.info(pkg) - log.errorf("error in parse file for indexing %v", fullpath) - } + file := ast.File { + fullpath = fullpath, + src = string(data), + pkg = pkg, + } - uri := common.create_uri(fullpath, context.allocator) + ok = parser.parse_file(&p, &file) - //collect_references(&symbol_collection, file, uri.uri) + if !ok { + log.info(pkg) + log.errorf("error in parse file for indexing %v", fullpath) + } - free_all(context.allocator) + uri := common.create_uri(fullpath, context.allocator) - delete(fullpath, allocator) - } - + { + context.temp_allocator = context.allocator + collect_references(&symbol_collection, file, uri.uri) + } + + free_all(context.allocator) - log.error(symbol_collection.references) + delete(fullpath, allocator) + } + } delete(files) delete(temp_arena.data) diff --git a/src/server/caches.odin b/src/server/caches.odin index 42dbc27..f446679 100644 --- a/src/server/caches.odin +++ b/src/server/caches.odin @@ -13,6 +13,7 @@ resolve_entire_file_cached :: proc(document: ^common.Document) -> map[uintptr]Sy if document.uri.uri not_in file_resolve_cache.files { file_resolve_cache.files[document.uri.uri] = resolve_entire_file( document, + false, common.scratch_allocator(document.allocator), ) } diff --git a/src/server/collector.odin b/src/server/collector.odin index b044f1c..632a94c 100644 --- a/src/server/collector.odin +++ b/src/server/collector.odin @@ -43,6 +43,7 @@ make_symbol_collection :: proc(allocator := context.allocator, config: ^common.C allocator = allocator, config = config, packages = make(map[string]map[string]Symbol, 16, allocator), + references = make(map[string]map[string]Reference, 100, allocator), unique_strings = make(map[string]string, 16, allocator), } } @@ -54,10 +55,13 @@ delete_symbol_collection :: proc(collection: SymbolCollection) { } } - for k, v in collection.references { - for k2, v2 in v { - common.free_ast(v2.identifiers, collection.allocator) - common.free_ast(v2.selectors, collection.allocator) + for _, pkg in collection.references { + for _, reference in pkg { + delete(reference.identifiers) + for _, field in reference.selectors { + delete(field) + } + delete(reference.selectors) } } @@ -80,7 +84,7 @@ delete_symbol_collection :: proc(collection: SymbolCollection) { collect_procedure_fields :: proc(collection: ^SymbolCollection, proc_type: ^ast.Proc_Type, arg_list: ^ast.Field_List, return_list: ^ast.Field_List, package_map: map[string]string) -> SymbolProcedureValue { returns := make([dynamic]^ast.Field, 0, collection.allocator) - args := make([dynamic]^ast.Field, 0, collection.allocator) + args := make([dynamic]^ast.Field, 0, collection.allocator) if return_list != nil { for ret in return_list.list { @@ -107,8 +111,8 @@ collect_procedure_fields :: proc(collection: ^SymbolCollection, proc_type: ^ast. } collect_struct_fields :: proc(collection: ^SymbolCollection, struct_type: ast.Struct_Type, package_map: map[string]string) -> SymbolStructValue { - names := make([dynamic]string, 0, collection.allocator) - types := make([dynamic]^ast.Expr, 0, collection.allocator) + names := make([dynamic]string, 0, collection.allocator) + types := make([dynamic]^ast.Expr, 0, collection.allocator) usings := make(map[string]bool, 0, collection.allocator) for field in struct_type.fields.list { @@ -385,8 +389,10 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri symbol.type = token_type symbol.doc = common.get_doc(expr.docs, collection.allocator) - if expr.builtin { + if expr.builtin || strings.contains(uri, "builtin.odin") { symbol.pkg = "$builtin" + } else if strings.contains(uri, "builtin.odin") { + symbol.pkg = "$intrinsics" } else { symbol.pkg = get_index_unique_string(collection, directory) } @@ -424,8 +430,8 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri } Reference :: struct { - identifiers: [dynamic]^ast.Ident, - selectors: [dynamic]^ast.Selector_Expr, + identifiers: [dynamic]common.Location, + selectors: map[string][dynamic]common.Range, } collect_references :: proc(collection: ^SymbolCollection, file: ast.File, uri: string) -> common.Error { @@ -442,13 +448,10 @@ collect_references :: proc(collection: ^SymbolCollection, file: ast.File, uri: s document.uri = uri document.text = transmute([]u8)file.src document.used_text = len(file.src) - document.allocator = document_get_allocator() - - context.allocator = common.scratch_allocator(document.allocator) parse_imports(&document, &common.config) - symbols_and_nodes := resolve_entire_file(&document, common.scratch_allocator(document.allocator)) + symbols_and_nodes := resolve_entire_file(&document, true) for k, v in symbols_and_nodes { pkg: ^map[string]Reference @@ -458,22 +461,28 @@ collect_references :: proc(collection: ^SymbolCollection, file: ast.File, uri: s pkg = &collection.references[v.symbol.pkg] } + assert(pkg != nil) + ref: ^Reference - if ref, ok := &pkg[v.symbol.name]; !ok { + if ref, ok = &pkg[v.symbol.name]; !ok { pkg[get_index_unique_string(collection, v.symbol.name)] = {} ref = &pkg[v.symbol.name] + ref.identifiers = make([dynamic]common.Location, 100, collection.allocator) + ref.selectors = make(map[string][dynamic]common.Range, 100, collection.allocator) } + assert(ref != nil) + if ident, ok := v.node.derived.(^ast.Ident); ok { - append(&ref.identifiers, cast(^ast.Ident)clone_type(ident, collection.allocator, nil)) + range := common.get_token_range(ident, ident.name) + append(&ref.identifiers, common.Location { range = range, uri = get_index_unique_string(collection, ident.pos.file) }) + } else if selector, ok := v.node.derived.(^ast.Selector_Expr); ok { - append(&ref.selectors, cast(^ast.Selector_Expr)clone_type(selector, collection.allocator, nil)) + //append(&ref.selectors, cast(^ast.Selector_Expr)clone_type(selector, collection.allocator, nil)) } } - document_free_allocator(document.allocator) - return .None } @@ -498,7 +507,7 @@ get_package_mapping :: proc(file: ast.File, config: ^common.Config, directory: s name: string - full := path.join(elems = {dir, p}, allocator = context.temp_allocator) + full := path.join(elems = {dir, p}, allocator = context.temp_allocator) if imp.name.text != "" { name = imp.name.text @@ -506,7 +515,7 @@ get_package_mapping :: proc(file: ast.File, config: ^common.Config, directory: s name = path.base(full, false, context.temp_allocator) } - package_map[name] = full + package_map[name] = full } else { name: string @@ -519,7 +528,7 @@ get_package_mapping :: proc(file: ast.File, config: ^common.Config, directory: s name = path.base(full, false, context.temp_allocator) } - package_map[name] = full + package_map[name] = full } } diff --git a/src/server/completion.odin b/src/server/completion.odin index 38a5baa..093c9e3 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -273,7 +273,6 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc if containsColor == 1 && containsCoord == 1 { save := expr_len for k in swizzle_color_components { - if expr_len <= 0 { break } @@ -359,7 +358,7 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc item.label = fmt.aprintf("(%v%v)", common.repeat("^", symbol.pointers, context.temp_allocator), symbol.name) } else { item.label = fmt.aprintf("(%v%v.%v)", common.repeat("^", symbol.pointers, context.temp_allocator), path.base(symbol.pkg, false, context.temp_allocator), symbol.name) - } + } append(&items, item) } @@ -374,7 +373,6 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc kind = .EnumMember, detail = fmt.tprintf("%v.%v", selector.name, name), } - append(&items, item) } @@ -470,7 +468,7 @@ get_implicit_completion :: proc(ast_context: ^AstContext, position_context: ^Doc selector: Symbol - ast_context.use_locals = true + ast_context.use_locals = true ast_context.use_globals = true if selector.pkg != "" { @@ -535,9 +533,7 @@ get_implicit_completion :: proc(ast_context: ^AstContext, position_context: ^Doc if position_context.assign != nil && position_context.assign.lhs != nil && len(position_context.assign.lhs) == 1 && is_bitset_assignment_operator(position_context.assign.op.text) { //bitsets if symbol, ok := resolve_type_expression(ast_context, position_context.assign.lhs[0]); ok { - if value, ok := unwrap_bitset(ast_context, symbol); ok { - for name in value.names { item := CompletionItem { @@ -559,9 +555,7 @@ get_implicit_completion :: proc(ast_context: ^AstContext, position_context: ^Doc //bitsets if symbol, ok := resolve_first_symbol_from_binary_expression(ast_context, position_context.parent_binary); ok { if value, ok := unwrap_bitset(ast_context, symbol); ok { - for name in value.names { - item := CompletionItem { label = name, kind = .EnumMember, @@ -675,10 +669,10 @@ get_implicit_completion :: proc(ast_context: ^AstContext, position_context: ^Doc if position_in_node(position_context.binary.right, position_context.position) { context_node = position_context.binary.right - enum_node = position_context.binary.left + enum_node = position_context.binary.left } else if position_in_node(position_context.binary.left, position_context.position) { context_node = position_context.binary.left - enum_node = position_context.binary.right + enum_node = position_context.binary.right } if context_node != nil && enum_node != nil { @@ -725,8 +719,8 @@ get_implicit_completion :: proc(ast_context: ^AstContext, position_context: ^Doc 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, + label = name, + kind = .EnumMember, detail = name, } @@ -1116,7 +1110,6 @@ get_package_completion :: proc(ast_context: ^AstContext, position_context: ^Docu if !strings.contains(position_context.import_stmt.fullpath, "/") && !strings.contains(position_context.import_stmt.fullpath, ":") { for key, _ in common.config.collections { - item := CompletionItem { detail = "collection", label = key, @@ -1125,7 +1118,6 @@ get_package_completion :: proc(ast_context: ^AstContext, position_context: ^Docu append(&items, item) } - } for pkg in search_for_packages(absolute_path) { @@ -1167,7 +1159,6 @@ search_for_packages :: proc(fullpath: string) -> [] string { } get_type_switch_completion :: proc(ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - items := make([dynamic]CompletionItem, context.temp_allocator) list.isIncomplete = false diff --git a/src/server/documents.odin b/src/server/documents.odin index b702e0c..62cc1ba 100644 --- a/src/server/documents.odin +++ b/src/server/documents.odin @@ -55,6 +55,7 @@ document_get_allocator :: proc() -> ^common.Scratch_Allocator { } document_free_allocator :: proc(allocator: ^common.Scratch_Allocator) { + free_all(common.scratch_allocator(allocator)) append(&document_storage.free_allocators, allocator) } @@ -226,7 +227,6 @@ document_close :: proc(uri_string: string) -> common.Error { return .InvalidRequest } - free_all(common.scratch_allocator(document.allocator)) document_free_allocator(document.allocator) document.allocator = nil @@ -330,19 +330,29 @@ parse_document :: proc(document: ^common.Document, config: ^common.Config) -> ([ context.allocator = common.scratch_allocator(document.allocator) - //have to cheat the parser since it really wants to parse an entire package with the new changes... + when ODIN_OS == .Windows { + fullpath, _ := filepath.to_slash(common.get_case_sensitive_path(document.uri.path)) + } else { + fullpath := document.uri.path + } + pkg := new(ast.Package) pkg.kind = .Normal - pkg.fullpath = document.uri.path + pkg.fullpath = fullpath document.ast = ast.File { - fullpath = document.uri.path, + fullpath = fullpath, src = string(document.text[:document.used_text]), pkg = pkg, } parser.parse_file(&p, &document.ast) + if len(document.ast.decls) >= 1 { + log.error(document.ast.decls[0]) + } + + parse_imports(document, config) return current_errors[:], true @@ -351,11 +361,17 @@ parse_document :: proc(document: ^common.Document, config: ^common.Config) -> ([ parse_imports :: proc(document: ^common.Document, config: ^common.Config) { imports := make([dynamic]common.Package) - document.package_name = path.dir(document.uri.path) - + //Right now not all clients return the case correct windows path, and that causes issues with indexing, so we ensure that it's case correct. when ODIN_OS == .Windows { - forward, _ := filepath.to_slash(common.get_case_sensitive_path(document.package_name), context.temp_allocator) - document.package_name = strings.clone(forward) + package_name := path.dir(document.uri.path, context.temp_allocator) + forward, _ := filepath.to_slash(common.get_case_sensitive_path(package_name), context.temp_allocator) + if forward == "" { + document.package_name = package_name + } else { + document.package_name = strings.clone(forward) + } + } else { + document.package_name = path.dir(document.uri.path) } for imp, index in document.ast.imports { @@ -365,7 +381,6 @@ parse_imports :: proc(document: ^common.Document, config: ^common.Config) { //collection specified if i := strings.index(imp.fullpath, ":"); i != -1 && i > 1 && i < len(imp.fullpath) - 1 { - if len(imp.fullpath) < 2 { continue } diff --git a/src/server/indexer.odin b/src/server/indexer.odin index 068a807..ce0404b 100644 --- a/src/server/indexer.odin +++ b/src/server/indexer.odin @@ -64,6 +64,9 @@ lookup :: proc(name: string, pkg: string, loc := #caller_location) -> (Symbol, b return {}, false } +lookup_reference :: proc(name: string, pkg: string) -> (Reference, bool) { + return memory_reference_lookup(&indexer.static_index, name, pkg) +} fuzzy_search :: proc(name: string, pkgs: []string) -> ([]FuzzyResult, bool) { dynamic_results, dynamic_ok := memory_index_fuzzy_search(&indexer.dynamic_index, name, pkgs) diff --git a/src/server/reader.odin b/src/server/reader.odin index be0d4ae..e704ad8 100644 --- a/src/server/reader.odin +++ b/src/server/reader.odin @@ -16,7 +16,6 @@ make_reader :: proc(reader_fn: ReaderFn, reader_context: rawptr) -> Reader { } read_u8 :: proc(reader: ^Reader) -> (u8, bool) { - value: [1]byte read, err := reader.reader_fn(reader.reader_context, value[:]) @@ -29,7 +28,6 @@ read_u8 :: proc(reader: ^Reader) -> (u8, bool) { } read_until_delimiter :: proc(reader: ^Reader, delimiter: u8, builder: ^strings.Builder) -> bool { - for true { value, success := read_u8(reader) diff --git a/src/server/references.odin b/src/server/references.odin index b7d1d47..5566234 100644 --- a/src/server/references.odin +++ b/src/server/references.odin @@ -7,7 +7,40 @@ import "core:strings" import "core:odin/ast" import "core:encoding/json" import path "core:path/slashpath" +import "core:log" get_references :: proc(document: ^common.Document, position: common.Position) -> ([]common.Location, bool) { - return {}, true + locations := make([dynamic]common.Location, context.temp_allocator) + + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) + + position_context, ok := get_document_position_context(document, position, .Hover) + + get_globals(document.ast, &ast_context) + + if position_context.function != nil { + get_locals(document.ast, position_context.function, &ast_context, &position_context) + } + + if position_context.identifier != nil { + ast_context.use_locals = true + ast_context.use_globals = true + ast_context.current_package = ast_context.document_package + + ident := position_context.identifier.derived.(^ast.Ident)^ + + if resolved, ok := resolve_type_identifier(&ast_context, ident); ok { + reference, _ := lookup_reference(resolved.name, resolved.pkg) + + for ident in reference.identifiers { + uri := common.create_uri(ident.uri, context.temp_allocator) + append(&locations, common.Location { uri = uri.uri, range = ident.range }) + } + } + + + } + + + return locations[:], true }
\ No newline at end of file diff --git a/src/server/requests.odin b/src/server/requests.odin index a217f27..6c9b396 100644 --- a/src/server/requests.odin +++ b/src/server/requests.odin @@ -386,7 +386,6 @@ request_initialize :: proc (params: json.Value, id: RequestId, config: ^common.C if data, ok := os.read_entire_file(file, context.temp_allocator); ok { if value, err := json.parse(data = data, allocator = context.temp_allocator, parse_integers = true); err == .None { - ols_config := OlsConfig { formatter = { characters = 90, @@ -515,8 +514,8 @@ request_initialize :: proc (params: json.Value, id: RequestId, config: ^common.C includeText = true, }, }, - renameProvider = true, - referencesProvider = true, + renameProvider = config.enable_rename, + referencesProvider = config.enable_references, definitionProvider = true, completionProvider = CompletionOptions { resolveProvider = false, diff --git a/src/server/signature.odin b/src/server/signature.odin index e866953..5f47381 100644 --- a/src/server/signature.odin +++ b/src/server/signature.odin @@ -44,7 +44,6 @@ SignatureInformation :: struct { ParameterInformation :: struct { label: string, - activeParameter: int, } /* @@ -176,15 +175,12 @@ get_signature_information :: proc(document: ^common.Document, position: common.P } else if value, ok := call.value.(SymbolAggregateValue); ok { //function overloaded procedures for symbol in value.symbols { - symbol := symbol if value, ok := symbol.value.(SymbolProcedureValue); ok { - parameters := make([]ParameterInformation, len(value.arg_types), context.temp_allocator) - for arg, i in value.arg_types { - + for arg, i in value.arg_types { if arg.type != nil { if _, is_ellipsis := arg.type.derived.(^ast.Ellipsis); is_ellipsis { signature_help.activeParameter = min(i, signature_help.activeParameter) @@ -192,7 +188,6 @@ get_signature_information :: proc(document: ^common.Document, position: common.P } parameters[i].label = common.node_to_string(arg) - parameters[i].activeParameter = i } build_procedure_symbol_signature(&symbol) @@ -200,7 +195,6 @@ get_signature_information :: proc(document: ^common.Document, position: common.P info := SignatureInformation { label = concatenate_symbol_information(&ast_context, symbol, false), documentation = symbol.doc, - parameters = parameters, } append(&signature_information, info) diff --git a/src/server/symbol.odin b/src/server/symbol.odin index 3a119ce..2d11114 100644 --- a/src/server/symbol.odin +++ b/src/server/symbol.odin @@ -115,6 +115,7 @@ SymbolFlag :: enum { PrivatePackage, Anonymous, //Usually applied to structs that are defined inline inside another struct Variable, //Symbols that are variable, this means their value decl was mutable + Local, } SymbolFlags :: bit_set[SymbolFlag] diff --git a/src/server/types.odin b/src/server/types.odin index d4be1af..6cab934 100644 --- a/src/server/types.odin +++ b/src/server/types.odin @@ -300,7 +300,6 @@ CompletionItem :: struct { tags: []CompletionItemTag, deprecated: bool, command: Command, - } CompletionItemTag :: enum { |