aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2020-12-09 17:36:44 +0100
committerDanielGavin <danielgavin5@hotmail.com>2020-12-09 17:36:44 +0100
commit07c7e937aaa2fe1c4c7813f4f7257ccafd45fabd (patch)
tree39f19e6dfb4740dad4b79f409026e24cda2e14cb /src/server
parent705f77aae24e383e6adc3cb92a48b60d22699e82 (diff)
combine results from local and indexer on non selection completion + fuzzer acronym
Diffstat (limited to 'src/server')
-rw-r--r--src/server/analysis.odin182
1 files changed, 150 insertions, 32 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index a75e475..cf68cd5 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -10,10 +10,14 @@ import "core:path"
import "core:mem"
import "core:strconv"
import "core:path/filepath"
+import "core:sort"
import "shared:common"
import "shared:index"
+/*
+ TODO(replace all of the possible ast walking with the new odin visitor function)
+*/
bool_lit := "bool";
int_lit := "int";
@@ -348,8 +352,6 @@ resolve_generic_function_symbol :: proc(ast_context: ^AstContext, params: []^ast
name = function_name,
};
- //symbol.signature = strings.concatenate( {"(", string(ast_context.file.src[params[0].pos.offset:params[len(params)-1].end.offset]), ")"}, context.temp_allocator);
-
return_types := make([dynamic] ^ast.Field, context.temp_allocator);
for result in results {
@@ -511,6 +513,18 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i
return resolve_type_identifier(ast_context, v);
case Basic_Lit:
return resolve_basic_lit(ast_context, v);
+ case Type_Cast:
+ return resolve_type_expression(ast_context, v.expr);
+ case Unary_Expr:
+ return resolve_type_expression(ast_context, v.expr);
+ case Deref_Expr:
+ return resolve_type_expression(ast_context, v.expr);
+ case Paren_Expr:
+ return resolve_type_expression(ast_context, v.expr);
+ case Slice_Expr:
+ return resolve_type_expression(ast_context, v.expr);
+ case Tag_Expr:
+ return resolve_type_expression(ast_context, v.expr);
case Type_Assertion:
resolve_type_expression(ast_context, v.type);
case Proc_Lit:
@@ -549,7 +563,6 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i
ast_context.call = node;
return resolve_type_expression(ast_context, v.expr);
case Implicit_Selector_Expr:
- log.info(v);
return index.Symbol {}, false;
case Selector_Expr:
@@ -561,7 +574,6 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i
case index.SymbolProcedureValue:
if len(s.return_types) == 1 {
- //ERROR wierd signature help index.new_type() (maybe generics problem)
selector_expr := index.new_type(ast.Selector_Expr, s.return_types[0].node.pos, s.return_types[0].node.end, context.temp_allocator);
selector_expr.expr = s.return_types[0].type;
selector_expr.field = v.field;
@@ -937,6 +949,30 @@ get_package_from_node :: proc(node: ast.Node) -> string {
return ret;
}
+get_using_packages :: proc(ast_context: ^AstContext) -> [] string {
+
+ usings := make([] string, len(ast_context.usings), context.temp_allocator);
+
+ if len(ast_context.usings) == 0 {
+ return usings;
+ }
+
+ //probably map instead
+ for u, i in ast_context.usings {
+
+ for imp in ast_context.imports {
+
+ if strings.compare(imp.base, u) == 0 {
+ usings[i] = imp.name;
+ }
+
+ }
+
+ }
+
+ return usings;
+}
+
make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, v: ast.Proc_Lit, name: string) -> index.Symbol {
symbol := index.Symbol {
@@ -983,7 +1019,6 @@ make_symbol_generic_from_ast :: proc(ast_context: ^AstContext, expr: ^ast.Expr)
range = common.get_token_range(expr, ast_context.file.src),
type = .Variable,
pkg = get_package_from_node(expr^),
- signature = common.get_ast_node_string(expr, ast_context.file.src),
};
symbol.value = index.SymbolGenericValue {
@@ -1824,63 +1859,120 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> (
else {
- log.infof("label %v", position_context.identifier);
+ list.isIncomplete = true;
- /*
- Just show the local and global symbols of the document
+ CombinedResult :: struct {
+ score: f32,
+ symbol: index.Symbol,
+ variable: ^ast.Ident,
+ };
- TODO(Add fuzzy matching)
- */
+ combined_sort_interface :: proc(s: ^[dynamic] CombinedResult) -> sort.Interface {
+ return sort.Interface{
+ collection = rawptr(s),
+ len = proc(it: sort.Interface) -> int {
+ s := (^[dynamic] CombinedResult)(it.collection);
+ return len(s^);
+ },
+ less = proc(it: sort.Interface, i, j: int) -> bool {
+ s := (^[dynamic] CombinedResult)(it.collection);
+ return s[i].score > s[j].score;
+ },
+ swap = proc(it: sort.Interface, i, j: int) {
+ s := (^[dynamic] CombinedResult)(it.collection);
+ s[i], s[j] = s[j], s[i];
+ },
+ };
+ }
- for k, v in ast_context.locals {
+ combined := make([dynamic] CombinedResult);
- item := CompletionItem {
- label = k,
- };
+ lookup := "";
- append(&items, item);
+ if ident, ok := position_context.identifier.derived.(ast.Ident); ok {
+ lookup = ident.name;
}
- for k, v in ast_context.globals {
- item := CompletionItem {
- label = k,
- };
+ pkgs := make([dynamic] string, context.temp_allocator);
- append(&items, item);
+ usings := get_using_packages(&ast_context);
+
+ for u in usings {
+ append(&pkgs, u);
}
- ident := index.new_type(ast.Ident, tokenizer.Pos {}, tokenizer.Pos {}, context.temp_allocator);
+ append(&pkgs, ast_context.document_package);
+
+ if results, ok := index.fuzzy_search(lookup, pkgs[:]); ok {
+
+ for r in results {
+ append(&combined, CombinedResult { score = r.score, symbol = r.symbol});
+ }
+
+ }
- for item, i in items {
+ matcher := common.make_fuzzy_matcher(lookup);
- ident.name = item.label;
+ for k, v in ast_context.locals {
ast_context.use_locals = true;
ast_context.use_globals = true;
ast_context.current_package = ast_context.document_package;
- if symbol, ok := resolve_type_identifier(&ast_context, ident^); ok {
+ ident := index.new_type(ast.Ident, tokenizer.Pos {}, tokenizer.Pos {}, context.temp_allocator);
+ ident.name = k;
+ if symbol, ok := resolve_type_identifier(&ast_context, ident^); ok {
symbol.name = ident.name;
- if ok := resolve_ident_is_variable(&ast_context, ident^); ok {
- items[i].kind = .Variable;
+ if score, ok := common.fuzzy_match(matcher, symbol.name); ok {
+ append(&combined, CombinedResult { score = score * 1.1, symbol = symbol, variable = ident });
+ }
+
+ }
+ }
+
+ sort.sort(combined_sort_interface(&combined));
+
+ //hard code for now
+ top_results := combined[0:(min(20, len(combined)))];
+
+ log.info(top_results);
+
+ for result in top_results {
+
+ item := CompletionItem {
+ label = result.symbol.name,
+ detail = concatenate_symbols_information(&ast_context, result.symbol),
+ };
+
+ if result.variable != nil {
+
+ if ok := resolve_ident_is_variable(&ast_context, result.variable^); ok {
+ item.kind = .Variable;
}
else {
- items[i].kind = cast(CompletionItemKind)symbol.type;
+ item.kind = cast(CompletionItemKind)result.symbol.type;
}
- items[i].detail = concatenate_symbols_information(&ast_context, symbol);
}
- //ERROR items[i].
+ else {
+ item.kind = cast(CompletionItemKind)result.symbol.type;
+ }
+
+ append(&items, item);
}
+
list.items = items[:];
}
+
+
+
return list, true;
}
@@ -2027,6 +2119,7 @@ fallback_position_context_completion :: proc(document: ^Document, position: comm
end: int;
start: int;
empty_dot: bool;
+ last_dot: bool;
i := position_context.position-1;
end = i;
@@ -2045,6 +2138,11 @@ fallback_position_context_completion :: proc(document: ^Document, position: comm
break;
}
+ else if c == ']' && !last_dot {
+ start = i+1;
+ break;
+ }
+
else if c == ')' {
paren_count -= 1;
}
@@ -2061,13 +2159,24 @@ fallback_position_context_completion :: proc(document: ^Document, position: comm
bracket_count -= 1;
}
+ else if c == '.' {
+ last_dot = true;
+ i -= 1;
+ continue;
+ }
+
+ //yeah..
if c == ' ' || c == '{' || c == ',' ||
c == '}' || c == '^' || c == ':' ||
- c == '\n' || c == '\r' {
+ c == '\n' || c == '\r' || c == '=' ||
+ c == '<' || c == '>' || c == '-' ||
+ c == '+' {
start = i+1;
break;
}
+ last_dot = false;
+
i -= 1;
}
@@ -2217,7 +2326,6 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP
case Bad_Expr:
case Ident:
position_context.identifier = node;
- return;
case Implicit:
case Undef:
case Basic_Lit:
@@ -2249,12 +2357,20 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP
get_document_position(n.expr, position_context);
get_document_position(n.args, position_context);
case Selector_Expr:
- if position_context.hint == .Completion || position_context.hint == .Definition {
+ if position_context.hint == .Completion {
if n.field != nil && n.field.pos.line == position_context.line {
position_context.selector = n.expr;
position_context.field = n.field;
}
}
+
+ else if position_context.hint == .Definition && n.field != nil {
+ position_context.selector = n.expr;
+ position_context.field = n.field;
+ get_document_position(n.expr, position_context);
+ get_document_position(n.field, position_context);
+ }
+
else {
get_document_position(n.expr, position_context);
get_document_position(n.field, position_context);
@@ -2411,6 +2527,8 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP
case Map_Type:
get_document_position(n.key, position_context);
get_document_position(n.value, position_context);
+ case Implicit_Selector_Expr:
+ get_document_position(n.field, position_context);
case:
log.errorf("Unhandled node kind: %T", n);
}