aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2022-06-11 11:46:14 +0200
committerDaniel Gavin <danielgavin5@hotmail.com>2022-06-11 11:46:14 +0200
commit70d5bcf8eca474440020c31239cd827cf3bb3415 (patch)
tree3fec51ed6f3257ad73b971e98dcb7c6b5e1f68fc /src
parenteda3110541a5a9f6f5e3b9428139f5d060e6a3ae (diff)
More reference work
Diffstat (limited to 'src')
-rw-r--r--src/common/config.odin3
-rw-r--r--src/common/position.odin4
-rw-r--r--src/common/util_windows.odin6
-rw-r--r--src/odin/printer/visit.odin5
-rw-r--r--src/server/analysis.odin155
-rw-r--r--src/server/build.odin83
-rw-r--r--src/server/caches.odin1
-rw-r--r--src/server/collector.odin53
-rw-r--r--src/server/completion.odin21
-rw-r--r--src/server/documents.odin33
-rw-r--r--src/server/indexer.odin3
-rw-r--r--src/server/reader.odin2
-rw-r--r--src/server/references.odin35
-rw-r--r--src/server/requests.odin5
-rw-r--r--src/server/signature.odin8
-rw-r--r--src/server/symbol.odin1
-rw-r--r--src/server/types.odin1
-rw-r--r--src/testing/testing.odin19
18 files changed, 260 insertions, 178 deletions
diff --git a/src/common/config.odin b/src/common/config.odin
index afdcdeb..387e8b8 100644
--- a/src/common/config.odin
+++ b/src/common/config.odin
@@ -15,6 +15,9 @@ Config :: struct {
enable_inlay_hints: bool,
enable_procedure_context: bool,
enable_snippets: bool,
+ enable_references: bool,
+ enable_rename: bool,
+ enable_std_references: bool,
thread_count: int,
file_log: bool,
formatter: Format_Config,
diff --git a/src/common/position.odin b/src/common/position.odin
index 2ccd0a8..3a600ab 100644
--- a/src/common/position.odin
+++ b/src/common/position.odin
@@ -42,8 +42,8 @@ get_absolute_position :: proc(position: Position, document_text: []u8) -> (Absol
}
line_count := 0
- index := 1
- last := document_text[0]
+ index := 1
+ last := document_text[0]
if !get_index_at_line(&index, &line_count, &last, document_text, position.line) {
return absolute, false
diff --git a/src/common/util_windows.odin b/src/common/util_windows.odin
index 5724275..194bd4d 100644
--- a/src/common/util_windows.odin
+++ b/src/common/util_windows.odin
@@ -28,7 +28,8 @@ foreign kernel32 {
}
get_case_sensitive_path :: proc(path: string, allocator := context.temp_allocator) -> string {
- file := win32.CreateFileW(&win32.utf8_to_utf16(path)[0], 0, win32.FILE_SHARE_READ, nil, win32.OPEN_EXISTING, win32.FILE_FLAG_BACKUP_SEMANTICS, nil)
+ wide := win32.utf8_to_utf16(path)
+ file := win32.CreateFileW(&wide[0], 0, win32.FILE_SHARE_READ, nil, win32.OPEN_EXISTING, win32.FILE_FLAG_BACKUP_SEMANTICS, nil)
if(file == win32.INVALID_HANDLE)
{
@@ -40,7 +41,8 @@ get_case_sensitive_path :: proc(path: string, allocator := context.temp_allocato
ret := win32.GetFinalPathNameByHandleW(file, &buffer[0], cast(u32)len(buffer), 0)
- res, _ := win32.utf16_to_utf8(buffer, allocator)
+ res, _ := win32.utf16_to_utf8(buffer[4:], allocator)
+
return res
}
diff --git a/src/odin/printer/visit.odin b/src/odin/printer/visit.odin
index f95fb3b..0a151ac 100644
--- a/src/odin/printer/visit.odin
+++ b/src/odin/printer/visit.odin
@@ -904,8 +904,7 @@ should_align_assignment_stmt :: proc(p: ^Printer, stmt: ast.Assign_Stmt) -> bool
if _, ok := stmt.rhs[0].derived.(^ast.Binary_Expr); ok {
return true
}
- }
-
+ }
return false
}
@@ -1123,7 +1122,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type =
document = cons(document, cons(newline(1), text_position(p, "}", v.end)))
}
-
+
set_source_position(p, v.end)
return document
case ^Proc_Lit:
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 {
diff --git a/src/testing/testing.odin b/src/testing/testing.odin
index 0335cce..c8ccc17 100644
--- a/src/testing/testing.odin
+++ b/src/testing/testing.odin
@@ -17,12 +17,12 @@ Package :: struct {
}
Source :: struct {
- main: string,
- packages: [] Package,
- document: ^common.Document,
- collections: map[string]string,
- config: common.Config,
- position: common.Position,
+ main: string,
+ packages: [] Package,
+ document: ^common.Document,
+ collections: map[string]string,
+ config: common.Config,
+ position: common.Position,
}
@(private)
@@ -89,9 +89,9 @@ setup :: proc(src: ^Source) {
dir := filepath.base(filepath.dir(fullpath, context.temp_allocator));
pkg := new(ast.Package);
- pkg.kind = .Normal;
+ pkg.kind = .Normal;
pkg.fullpath = fullpath;
- pkg.name = dir;
+ pkg.name = dir;
if dir == "runtime" {
pkg.kind = .Runtime;
@@ -199,7 +199,6 @@ expect_completion_labels :: proc(t: ^testing.T, src: ^Source, trigger_character:
testing.errorf(t, "Expected completion detail %v, but received %v", expect_labels[i], completion_list.items);
}
}
-
}
expect_completion_details :: proc(t: ^testing.T, src: ^Source, trigger_character: string, expect_details: []string) {
@@ -235,7 +234,6 @@ expect_completion_details :: proc(t: ^testing.T, src: ^Source, trigger_character
testing.errorf(t, "Expected completion label %v, but received %v", expect_details[i], completion_list.items);
}
}
-
}
expect_hover :: proc(t: ^testing.T, src: ^Source, expect_hover_string: string) {
@@ -255,7 +253,6 @@ expect_hover :: proc(t: ^testing.T, src: ^Source, expect_hover_string: string) {
if !strings.contains(hover.contents.value, expect_hover_string) {
testing.errorf(t, "Expected hover string %v, but received %v", expect_hover_string, hover.contents.value);
}
-
}
expect_definition_locations :: proc(t: ^testing.T, src: ^Source, expect_locations: []common.Location) {