diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2020-11-12 15:50:42 +0100 |
|---|---|---|
| committer | DanielGavin <danielgavin5@hotmail.com> | 2020-11-12 15:50:42 +0100 |
| commit | 091efd3e488482a20fc4f3cbf109814e2705d8ef (patch) | |
| tree | 09cb0f43e634824437ea3fa0d27f76349ad0653c | |
| parent | 2fba6caddadc6d7d10f6af5892de6fd44d2291d4 (diff) | |
can now handle the bad expression where field is in specified in the selector expression.
| -rw-r--r-- | src/common/ast.odin | 4 | ||||
| -rw-r--r-- | src/index/symbol.odin | 8 | ||||
| -rw-r--r-- | src/server/analysis.odin | 160 | ||||
| -rw-r--r-- | src/server/documents.odin | 5 | ||||
| -rw-r--r-- | src/server/requests.odin | 2 |
5 files changed, 134 insertions, 45 deletions
diff --git a/src/common/ast.odin b/src/common/ast.odin index 15c4891..cc8ad83 100644 --- a/src/common/ast.odin +++ b/src/common/ast.odin @@ -10,4 +10,8 @@ get_ast_node_string :: proc(node: ^ast.Node, src: [] byte) -> string { free_ast_node :: proc(file: ^ast.Node) { +} + +free_ast_file :: proc(file: ast.File) { + }
\ No newline at end of file diff --git a/src/index/symbol.odin b/src/index/symbol.odin index 90e2a88..d55acc6 100644 --- a/src/index/symbol.odin +++ b/src/index/symbol.odin @@ -16,7 +16,7 @@ import "shared:common" SymbolStructValue :: struct { names: [] string, - types: [] ^ast.Node, + types: [] ^ast.Expr, }; SymbolValue :: union { @@ -35,8 +35,10 @@ Symbol :: struct { SymbolType :: enum { Function = 3, + Field = 5, + Package = 9, //set by ast symbol + Keyword = 14, //set by ast symbol Struct = 22, - Package = 9, //not used by the indexer itself but can be set when creating symbols from ast }; SymbolCollection :: struct { @@ -67,7 +69,7 @@ make_symbol_collection :: proc(allocator := context.allocator) -> SymbolCollecti collect_struct_fields :: proc(collection: ^SymbolCollection, fields: ^ast.Field_List, src: [] byte) -> SymbolStructValue { names := make([dynamic] string, 0, collection.allocator); - types := make([dynamic] ^ast.Node, 0, collection.allocator); + types := make([dynamic] ^ast.Expr, 0, collection.allocator); for field in fields.list { diff --git a/src/server/analysis.odin b/src/server/analysis.odin index a1300fc..57b9beb 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -20,6 +20,7 @@ DocumentPositionContextHint :: enum { }; DocumentPositionContext :: struct { + file: ast.File, position: common.AbsolutePosition, function: ^ast.Node, //used to help with type resolving in function scope selector: ^ast.Expr, //used for completion @@ -58,16 +59,23 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i case Ident: return resolve_type_identifier(ast_context, v); case Selector_Expr: - log.info("another selector"); - //selector, ok := resolve_type_expression(ast_context, v.expr); - //switch s in selector.value { - //case: - //} + if selector, ok := resolve_type_expression(ast_context, v.expr); ok { + + switch s in selector.value { + case index.SymbolStructValue: + 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]); + } + } + } + } - case: - //return "", false; + else { + return index.Symbol {}, false; + } } return index.Symbol {}, false; @@ -97,7 +105,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i } - if global, ok := ast_context.globals[node.name]; ok { + else if global, ok := ast_context.globals[node.name]; ok { switch v in global.derived { case Ident: @@ -112,6 +120,15 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i } + else if node.name == "int" { + + symbol := index.Symbol { + type = .Keyword, + }; + + return symbol, true; + } + return index.Symbol {}, false; } @@ -149,6 +166,24 @@ make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type type = .Struct, }; + names := make([dynamic] string, 0, context.temp_allocator); + types := make([dynamic] ^ast.Expr, 0, context.temp_allocator); + + for field in v.fields.list { + + for n in field.names { + identifier := n.derived.(ast.Ident); + append(&names, identifier.name); + append(&types, ast.clone_expr(field.type)); + } + + } + + symbol.value = index.SymbolStructValue { + names = names[:], + types = types[:], + }; + return symbol; } @@ -232,7 +267,7 @@ get_definition_location :: proc(document: ^Document, position: common.Position) ast_context := make_ast_context(); - symbol: index.Symbol; + uri: string; position_context, ok := get_document_position_context(document, position, .Definition); @@ -247,21 +282,11 @@ get_definition_location :: proc(document: ^Document, position: common.Position) get_locals(document.ast, position_context.function, &ast_context); } - /* - fmt.println(""); - fmt.println("locals"); - fmt.println(ast_context.locals); - - fmt.println(""); - fmt.println("globals: "); - fmt.println(ast_context.globals); - */ - - if position_context.identifier != nil { if resolved, ok := resolve_location_identifier(&ast_context, position_context.identifier.derived.(ast.Ident)); ok { - symbol = resolved; + location.range = resolved.range; + location.uri = resolved.uri; } else { @@ -289,7 +314,14 @@ get_definition_location :: proc(document: ^Document, position: common.Position) return location, false; } - //symbol, ok = index.lookup(strings.concatenate({selector, field}, context.temp_allocator)); + switch v in selector.value { + case index.SymbolStructValue: + for name, i in v.names { + if strings.compare(name, field) == 0 { + location.range = common.get_token_range(v.types[i]^, document.ast.src); + } + } + } if !ok { return location, false; @@ -301,22 +333,22 @@ get_definition_location :: proc(document: ^Document, position: common.Position) return location, false; } - location.range = symbol.range; - - if symbol.uri == "" { + //if the symbol is generated by the ast we don't set the uri. + if uri == "" { location.uri = document.uri.uri; } else { - location.uri = symbol.uri; + location.uri = uri; } - return location, true; } get_completion_list :: proc(document: ^Document, position: common.Position) -> (CompletionList, bool) { + symbols := make([dynamic] index.Symbol, 0, context.temp_allocator); + list: CompletionList; ast_context := make_ast_context(); @@ -328,20 +360,23 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> ( if position_context.function != nil { get_locals(document.ast, position_context.function, &ast_context); } - /* - symbols: [] index.Symbol; - //if we have format "selector.access" with plain identifiers - if position_context.selector != nil && position_context.field != nil { + items := make([dynamic] CompletionItem, 0, context.temp_allocator); + + //log.info(position_context); + + if position_context.selector != nil { - selector: string; + selector: index.Symbol; selector, ok = resolve_type_expression(&ast_context, position_context.selector); if !ok { + log.error("Failed to resolve type selector"); return list, true; } + /* field: string; switch v in position_context.field.derived { @@ -350,27 +385,43 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> ( case: return list, true; } + */ - symbols, ok = index.fuzzy_search(field, {selector}); + switch v in selector.value { + case index.SymbolStructValue: + for name, i in v.names { - if !ok { - return list, false; + if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok { + symbol.name = name; + symbol.type = .Field; + append(&symbols, symbol); + } + + } + + list.isIncomplete = true; } + //symbols, ok = index.fuzzy_search(field, {selector}); + + //if !ok { + // return list, false; + //} + } else { return list, true; } - list.items = make([] CompletionItem, len(symbols), context.temp_allocator); for symbol, i in symbols { list.items[i].label = symbol.name; list.items[i].kind = cast(CompletionItemKind) symbol.type; } - */ + + log.info(list); return list, true; } @@ -395,6 +446,7 @@ get_document_position_context :: proc(document: ^Document, position: common.Posi position_context: DocumentPositionContext; position_context.hint = hint; + position_context.file = document.ast; absolute_position, ok := common.get_absolute_position(position, document.text); @@ -409,9 +461,6 @@ get_document_position_context :: proc(document: ^Document, position: common.Posi get_document_position(decl, &position_context); } - - //fmt.println(position_context); - return position_context, true; } @@ -455,6 +504,35 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP switch n in node.derived { case Bad_Expr: + if position_context.hint == .Completion && position_context.file.src[max(0, node.end.offset-1)] == '.' { + + str := position_context.file.src[node.pos.offset:max(0, node.end.offset-1)]; + + p := parser.default_parser(); + + tokenizer.init(&p.tok, str, position_context.file.fullpath); + + parser.advance_token(&p); + + //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; + } + + else { + //this might not hold be enough in the future + e := parser.parse_ident(&p); //MEMORY LEAK - need to modify parser to allow for temp allocator + position_context.selector = e; + } + + + } + case Ident: position_context.identifier = node; return; @@ -476,8 +554,10 @@ 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 d68bb57..7759616 100644 --- a/src/server/documents.odin +++ b/src/server/documents.odin @@ -257,6 +257,9 @@ document_close :: proc(uri_string: string) -> common.Error { delete(document.text); + common.free_ast_file(document.ast); + + return .None; } @@ -388,6 +391,8 @@ parse_document :: proc(document: ^Document, config: ^common.Config) -> ([] Parse src = document.text[:document.used_text], }; + common.free_ast_file(document.ast); + parser.parse_file(&p, &document.ast); /* diff --git a/src/server/requests.odin b/src/server/requests.odin index 8775bd2..5dfe524 100644 --- a/src/server/requests.odin +++ b/src/server/requests.odin @@ -341,8 +341,6 @@ request_completion :: proc(params: json.Value, id: RequestId, config: ^common.Co list.isIncomplete = true; - - if !ok { return .InternalError; } |