diff options
| author | Daniel Gavin <danielgavin5@hotmail.com> | 2022-01-15 01:05:23 +0100 |
|---|---|---|
| committer | Daniel Gavin <danielgavin5@hotmail.com> | 2022-01-15 01:05:23 +0100 |
| commit | f3bfad6da8932b2d5c6a9cba430701b0a67e422c (patch) | |
| tree | a7b0c3b8941c99b0081ec9f57fb670f8c79685a6 /src | |
| parent | bd3f707d8e0a717df49b7bf702a5b98d214b0381 (diff) | |
refractor + more tests
Diffstat (limited to 'src')
| -rw-r--r-- | src/analysis/analysis.odin | 101 | ||||
| -rw-r--r-- | src/server/completion.odin | 52 | ||||
| -rw-r--r-- | src/testing/testing.odin | 1 |
3 files changed, 100 insertions, 54 deletions
diff --git a/src/analysis/analysis.odin b/src/analysis/analysis.odin index ec9f71e..ec7bb2c 100644 --- a/src/analysis/analysis.odin +++ b/src/analysis/analysis.odin @@ -68,7 +68,7 @@ DocumentLocal :: struct { } AstContext :: struct { - locals: map[string][dynamic]DocumentLocal, //locals all the way to the document position + locals: [dynamic]map[string][dynamic]DocumentLocal, //locals all the way to the document position globals: map[string]common.GlobalExpr, variables: map[string]bool, parameters: map[string]bool, @@ -81,7 +81,7 @@ AstContext :: struct { document_package: string, use_globals: bool, use_locals: bool, - local_id: int, + local_id: int, call: ^ast.Call_Expr, //used to determene the types for generics and the correct function for overloaded functions position: common.AbsolutePosition, value_decl: ^ast.Value_Decl, @@ -92,7 +92,7 @@ AstContext :: struct { make_ast_context :: proc(file: ast.File, imports: []common.Package, package_name: string, uri: string, symbol_cache: ^map[int]rawptr, allocator := context.temp_allocator) -> AstContext { ast_context := AstContext { - locals = make(map[string][dynamic]DocumentLocal, 0, allocator), + locals = make([dynamic]map[string][dynamic]DocumentLocal, 0, allocator), globals = make(map[string]common.GlobalExpr, 0, allocator), variables = make(map[string]bool, 0, allocator), usings = make([dynamic]string, allocator), @@ -108,6 +108,8 @@ make_ast_context :: proc(file: ast.File, imports: []common.Package, package_name symbol_cache = symbol_cache, }; + append(&ast_context.locals, make(map[string][dynamic]DocumentLocal, 0, allocator)); + when ODIN_OS == "windows" { ast_context.uri = strings.to_lower(ast_context.uri, allocator); } @@ -850,7 +852,7 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i if symbol, ok := internal_resolve_type_expression(ast_context, node); ok { cached_symbol := index.new_clone_symbol(symbol); - ast_context.symbol_cache[node.pos.offset] = cast(rawptr)cached_symbol; + ast_context.symbol_cache[node.end.offset] = cast(rawptr)cached_symbol; return symbol, true; } @@ -1062,17 +1064,21 @@ internal_resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex } store_local :: proc(ast_context: ^AstContext, expr: ^ast.Expr, offset: int, name: string, id := 0) { - local_stack := &ast_context.locals[name]; + local_stack := &ast_context.locals[id][name]; if local_stack == nil { - ast_context.locals[name] = make([dynamic]DocumentLocal, context.temp_allocator); - local_stack = &ast_context.locals[name]; + ast_context.locals[id][name] = make([dynamic]DocumentLocal, context.temp_allocator); + local_stack = &ast_context.locals[id][name]; } append(local_stack, DocumentLocal {expr = expr, offset = offset, id = id}); } -get_local :: proc(ast_context: ^AstContext, offset: int, name: string, id := 0) -> ^ast.Expr { +clear_local :: proc(ast_context: ^AstContext, id: int) { + ordered_remove(&ast_context.locals, id); +} + +get_local :: proc(ast_context: ^AstContext, offset: int, name: string) -> ^ast.Expr { previous := 0; //is the local we are getting being declared? @@ -1087,14 +1093,16 @@ get_local :: proc(ast_context: ^AstContext, offset: int, name: string, id := 0) } } - if local_stack, ok := ast_context.locals[name]; ok { - for i := len(local_stack) - 1; i >= 0; i -= 1 { - if local_stack[i].offset <= offset && local_stack[i].id == id { - if i - previous < 0 { - return nil; - } else { - return local_stack[i - previous].expr; - } + for locals in &ast_context.locals { + if local_stack, ok := locals[name]; ok { + for i := len(local_stack) - 1; i >= 0; i -= 1 { + if local_stack[i].offset <= offset { + if i - previous < 0 { + return nil; + } else { + return local_stack[i - previous].expr; + } + } } } } @@ -1102,18 +1110,21 @@ get_local :: proc(ast_context: ^AstContext, offset: int, name: string, id := 0) return nil; } -get_local_offset :: proc(ast_context: ^AstContext, offset: int, name: string, id := 0) -> int { - if local_stack, ok := ast_context.locals[name]; ok { - for i := len(local_stack) - 1; i >= 0; i -= 1 { - if local_stack[i].offset <= offset && local_stack[i].id == id { - if i < 0 { - return -1; - } else { - return local_stack[i].offset; - } +get_local_offset :: proc(ast_context: ^AstContext, offset: int, name: string) -> int { + for locals in &ast_context.locals { + if local_stack, ok := locals[name]; ok { + for i := len(local_stack) - 1; i >= 0; i -= 1 { + if local_stack[i].offset <= offset { + if i < 0 { + return -1; + } else { + return local_stack[i].offset; + } + } } } } + return -1; } @@ -1126,7 +1137,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i if symbol, ok := internal_resolve_type_identifier(ast_context, node); ok { cached_symbol := index.new_clone_symbol(symbol); - ast_context.symbol_cache[node.pos.offset] = cast(rawptr)cached_symbol; + ast_context.symbol_cache[node.end.offset] = cast(rawptr)cached_symbol; return symbol, true; } @@ -1283,6 +1294,7 @@ internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ide } else if node.name == "context" { for built in index.indexer.builtin_packages { if symbol, ok := index.lookup("Context", built); ok { + symbol.type = .Variable; return symbol, ok; } } @@ -2472,25 +2484,58 @@ resolve_entire_file :: proc(document: ^common.Document, allocator := context.all } resolve_entire_procedure :: proc(ast_context: ^AstContext, procedure: ast.Proc_Lit, symbols: ^[dynamic]index.Symbol, allocator := context.allocator) { + + Scope :: struct { + offset: int, + id: int, + } + Visit_Data :: struct { ast_context: ^AstContext, symbols: ^[dynamic]index.Symbol, + scopes: [dynamic]Scope, + id_counter: int, } data := Visit_Data { ast_context = ast_context, symbols = symbols, + scopes = make([dynamic]Scope, allocator), }; visit :: proc(visitor: ^ast.Visitor, node: ^ast.Node) -> ^ast.Visitor { if node == nil || visitor == nil { return nil; } - data := cast(^Visit_Data)visitor.data; ast_context := data.ast_context; + //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]; + + if current_scope.offset < node.end.offset { + clear_local(ast_context, current_scope.id); + + pop(&data.scopes); + + if len(data.scopes) > 0 { + current_scope = data.scopes[len(data.scopes)-1]; + ast_context.local_id = current_scope.id; + } else { + ast_context.local_id = 0; + } + } + } + switch v in &node.derived { + case ast.If_Stmt, ast.For_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); case ast.Ident: if symbol, ok := resolve_type_identifier(ast_context, v); ok { append(data.symbols, symbol); @@ -2530,7 +2575,7 @@ concatenate_raw_string_information :: proc(ast_context: ^AstContext, pkg: string pkg := path.base(pkg, false, context.temp_allocator); if type == .Package { - return name; + return fmt.tprintf("%v: package", name); } else if type == .Keyword && is_completion { return name; } else { diff --git a/src/server/completion.odin b/src/server/completion.odin index 6eba90f..1d20cec 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -862,8 +862,8 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co } } - ast_context.use_locals = true; - ast_context.use_globals = true; + ast_context.use_locals = true; + ast_context.use_globals = true; ast_context.current_package = ast_context.document_package; ident := index.new_type(ast.Ident, v.expr.pos, v.expr.end, context.temp_allocator); @@ -888,35 +888,37 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co } } - for k, v in ast_context.locals { - if position_context.global_lhs_stmt { - break; - } + for local in ast_context.locals { + for k, v in local { + if position_context.global_lhs_stmt { + break; + } - local_offset := get_local_offset(ast_context, position_context.position, k); + local_offset := get_local_offset(ast_context, position_context.position, k); - ast_context.use_locals = true; - ast_context.use_globals = true; - ast_context.current_package = ast_context.document_package; + ast_context.use_locals = true; + ast_context.use_globals = true; + ast_context.current_package = ast_context.document_package; - ident := index.new_type(ast.Ident, {offset = local_offset}, {offset = local_offset}, context.temp_allocator); - ident.name = k; + ident := index.new_type(ast.Ident, {offset = local_offset}, {offset = local_offset}, context.temp_allocator); + ident.name = k; - if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { - symbol.signature = get_signature(ast_context, ident^, symbol); + if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { + symbol.signature = get_signature(ast_context, ident^, symbol); - build_procedure_symbol_signature(&symbol); + build_procedure_symbol_signature(&symbol); - if score, ok := common.fuzzy_match(matcher, ident.name); ok == 1 { - append(&combined, CombinedResult { - score = score * 1.1, - type = symbol.type, - name = ident.name, - doc = symbol.doc, - flags = symbol.flags, - pkg = symbol.pkg, - signature = symbol.signature, - }); + if score, ok := common.fuzzy_match(matcher, ident.name); ok == 1 { + append(&combined, CombinedResult { + score = score * 1.1, + type = symbol.type, + name = ident.name, + doc = symbol.doc, + flags = symbol.flags, + pkg = symbol.pkg, + signature = symbol.signature, + }); + } } } } diff --git a/src/testing/testing.odin b/src/testing/testing.odin index c9c515d..4a40f16 100644 --- a/src/testing/testing.odin +++ b/src/testing/testing.odin @@ -29,7 +29,6 @@ Source :: struct { @(private) setup :: proc(src: ^Source) { - src.main = strings.clone(src.main); src.document = new(common.Document, context.temp_allocator); src.document.uri = common.create_uri("test/test.odin", context.temp_allocator); |