aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2020-11-12 15:50:42 +0100
committerDanielGavin <danielgavin5@hotmail.com>2020-11-12 15:50:42 +0100
commit091efd3e488482a20fc4f3cbf109814e2705d8ef (patch)
tree09cb0f43e634824437ea3fa0d27f76349ad0653c /src
parent2fba6caddadc6d7d10f6af5892de6fd44d2291d4 (diff)
can now handle the bad expression where field is in specified in the selector expression.
Diffstat (limited to 'src')
-rw-r--r--src/common/ast.odin4
-rw-r--r--src/index/symbol.odin8
-rw-r--r--src/server/analysis.odin160
-rw-r--r--src/server/documents.odin5
-rw-r--r--src/server/requests.odin2
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;
}