aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2021-02-20 21:55:22 +0100
committerDanielGavin <danielgavin5@hotmail.com>2021-02-20 21:55:22 +0100
commit70bac15e723f7304fbc45523b41597e43b129781 (patch)
treef1410d71c10127f5ea58475934e4c646edd4482c /src/server
parent23415f082147042b1d70c353a26b9735cb2ead2a (diff)
add selector expr + clean up + random fixes
Diffstat (limited to 'src/server')
-rw-r--r--src/server/analysis.odin103
-rw-r--r--src/server/completion.odin91
-rw-r--r--src/server/requests.odin2
3 files changed, 72 insertions, 124 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 8a5843e..119dfa5 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -46,6 +46,7 @@ DocumentPositionContext :: struct {
comp_lit: ^ast.Comp_Lit, //used for completion
parent_comp_lit: ^ast.Comp_Lit, //used for completion
implicit: bool, //used for completion
+ arrow: bool,
binary: ^ast.Binary_Expr, //used for completion
assign: ^ast.Assign_Stmt, //used for completion
value_decl: ^ast.Value_Decl,
@@ -74,6 +75,7 @@ AstContext :: struct {
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,
+ field_name: string,
};
make_ast_context :: proc(file: ast.File, imports: [] Package, package_name: string, allocator := context.temp_allocator) -> AstContext {
@@ -567,6 +569,8 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i
using ast;
switch v in node.derived {
+ case Proc_Type:
+ return make_symbol_procedure_from_ast(ast_context, node, v, ast_context.field_name), true;
case Ident:
return resolve_type_identifier(ast_context, v);
case Basic_Lit:
@@ -647,6 +651,8 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i
return resolve_type_expression(ast_context, v.expr);
case Implicit_Selector_Expr:
return index.Symbol {}, false;
+ case Selector_Call_Expr:
+ return resolve_type_expression(ast_context, v.expr);
case Selector_Expr:
if selector, ok := resolve_type_expression(ast_context, v.expr); ok {
@@ -672,7 +678,8 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i
}
for name, i in s.names {
- if v.field != nil && strings.compare(name, v.field.name) == 0 {
+ if v.field != nil && name == v.field.name {
+ ast_context.field_name = v.field.name;
return resolve_type_expression(ast_context, s.types[i]);
}
}
@@ -687,48 +694,14 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i
else {
return index.Symbol {}, false;
}
- case index.SymbolGenericValue:
-
- /*
- Slighty awkward, but you could have a pointer to struct, so have to check, i don't want to remove the pointer info by storing into the struct symbol value,
- since it can be used for signature infering.
- */
-
- if ptr, ok := s.expr.derived.(Pointer_Type); ok {
-
- if symbol, ok := resolve_type_expression(ast_context, ptr.elem); ok {
-
- #partial switch s2 in symbol.value {
- case index.SymbolStructValue:
-
- if selector.pkg != "" {
- ast_context.current_package = symbol.pkg;
- }
-
- else {
- ast_context.current_package = ast_context.document_package;
- }
-
- for name, i in s2.names {
- if v.field != nil && strings.compare(name, v.field.name) == 0 {
- return resolve_type_expression(ast_context, s2.types[i]);
- }
- }
-
- }
- }
-
- }
-
}
-
}
else {
return index.Symbol {}, false;
}
case:
- log.debugf("default node kind, resolve_type_expression: %T", v);
+ log.errorf("default node kind, resolve_type_expression: %T", v);
if v == nil {
return {}, false;
@@ -779,9 +752,14 @@ get_local :: proc(ast_context: ^AstContext, offset: int, name: string) -> ^ast.E
for i := len(local_stack)-1; i >= 0; i -= 1 {
if local_stack[i].offset <= offset {
+ log.errorf(" found %v %v", local_stack[i].offset, offset);
return local_stack[max(0, i - previous)].expr;
}
+ else {
+ log.errorf("not found %v %v", local_stack[i].offset, offset);
+ }
+
}
}
@@ -842,7 +820,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
return make_symbol_bitset_from_ast(ast_context, v, node), true;
case Proc_Lit:
if !v.type.generic {
- return make_symbol_procedure_from_ast(ast_context, v, node.name), true;
+ return make_symbol_procedure_from_ast(ast_context, local, v.type^, node.name), true;
}
else {
return resolve_generic_function(ast_context, v);
@@ -884,7 +862,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
return make_symbol_enum_from_ast(ast_context, v, node), true;
case Proc_Lit:
if !v.type.generic {
- return make_symbol_procedure_from_ast(ast_context, v, node.name), true;
+ return make_symbol_procedure_from_ast(ast_context, global, v.type^, node.name), true;
}
else {
return resolve_generic_function(ast_context, v);
@@ -900,7 +878,6 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
case:
log.warnf("default type node kind: %T", v);
return resolve_type_expression(ast_context, global);
- //return make_symbol_generic_from_ast(ast_context, global), true;
}
}
@@ -1014,7 +991,7 @@ resolve_ident_is_package :: proc(ast_context: ^AstContext, node: ast.Ident) ->
for imp in ast_context.imports {
- if strings.compare(imp.base, node.name) == 0 {
+ if imp.base == node.name {
return true;
}
@@ -1181,12 +1158,12 @@ get_using_packages :: proc(ast_context: ^AstContext) -> [] string {
return usings;
}
-make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, v: ast.Proc_Lit, name: string) -> index.Symbol {
+make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, v: ast.Proc_Type, name: string) -> index.Symbol {
symbol := index.Symbol {
- range = common.get_token_range(v, ast_context.file.src),
+ range = common.get_token_range(n^, ast_context.file.src),
type = .Function,
- pkg = get_package_from_node(v.node),
+ pkg = get_package_from_node(n^),
};
symbol.name = name;
@@ -1194,23 +1171,23 @@ make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, v: ast.Proc_Lit
return_types := make([dynamic] ^ast.Field, context.temp_allocator);
arg_types := make([dynamic] ^ast.Field, context.temp_allocator);
- if v.type.results != nil {
+ if v.results != nil {
- for ret in v.type.results.list {
+ for ret in v.results.list {
append(&return_types, ret);
}
- symbol.returns = strings.concatenate( {"(", string(ast_context.file.src[v.type.results.pos.offset:v.type.results.end.offset]), ")"}, context.temp_allocator);
+ symbol.returns = strings.concatenate( {"(", string(ast_context.file.src[v.results.pos.offset:v.results.end.offset]), ")"}, context.temp_allocator);
}
- if v.type.params != nil {
+ if v.params != nil {
- for param in v.type.params.list {
+ for param in v.params.list {
append(&arg_types, param);
}
- symbol.signature = strings.concatenate( {"(", string(ast_context.file.src[v.type.params.pos.offset:v.type.params.end.offset]), ")"}, context.temp_allocator);
+ symbol.signature = strings.concatenate( {"(", string(ast_context.file.src[v.params.pos.offset:v.params.end.offset]), ")"}, context.temp_allocator);
}
symbol.value = index.SymbolProcedureValue {
@@ -1568,11 +1545,10 @@ get_locals_value_decl :: proc(file: ast.File, value_decl: ast.Value_Decl, ast_co
ast_context.in_package[str] = get_package_from_node(results[i]);
store_local(ast_context, results[i], name.pos.offset, str);
ast_context.variables[str] = value_decl.is_mutable;
+ log.error(name);
}
}
-
-
}
get_locals_stmt :: proc(file: ast.File, stmt: ^ast.Stmt, ast_context: ^AstContext, document_position: ^DocumentPositionContext, save_assign := false) {
@@ -1683,6 +1659,7 @@ get_locals_assign_stmt :: proc(file: ast.File, stmt: ast.Assign_Stmt, ast_contex
if ident, ok := lhs.derived.(ast.Ident); ok {
store_local(ast_context, results[i], ident.pos.offset, ident.name);
ast_context.variables[ident.name] = true;
+ log.errorf("store %v ", ident.name);
}
}
@@ -2228,7 +2205,7 @@ get_document_symbols :: proc(document: ^Document) -> [] DocumentSymbol {
}
/*
- All these fallback functions are differently not perfect and should be fixed. A lot of weird use of the odin tokenizer and parser.
+ All these fallback functions are not perfect and should be fixed. A lot of weird use of the odin tokenizer and parser.
*/
/*
@@ -2274,7 +2251,10 @@ fallback_position_context_completion :: proc(document: ^Document, position: comm
end: int;
start: int;
empty_dot: bool;
+ empty_arrow: bool;
last_dot: bool;
+ last_arrow: bool;
+
i := position_context.position-1;
end = i;
@@ -2325,6 +2305,12 @@ fallback_position_context_completion :: proc(document: ^Document, position: comm
continue;
}
+ else if position_context.file.src[max(0, i-1)] == '-' && c == '>' {
+ last_arrow = true;
+ i -= 2;
+ continue;
+ }
+
//yeah..
if c == ' ' || c == '{' || c == ',' ||
c == '}' || c == '^' || c == ':' ||
@@ -2336,6 +2322,7 @@ fallback_position_context_completion :: proc(document: ^Document, position: comm
}
last_dot = false;
+ last_arrow = false;
i -= 1;
}
@@ -2345,6 +2332,12 @@ fallback_position_context_completion :: proc(document: ^Document, position: comm
end -= 1;
}
+ else if i >= 0 && position_context.file.src[max(0, end-1)] == '-' && position_context.file.src[end] == '>' {
+ empty_arrow = true;
+ end -= 2;
+ position_context.arrow = true;
+ }
+
begin_offset := max(0, start);
end_offset := max(start, end+1);
@@ -2355,7 +2348,7 @@ fallback_position_context_completion :: proc(document: ^Document, position: comm
return;
}
- log.infof("parser string %v", string(str));
+ //log.errorf("parser string %v", string( position_context.file.src[begin_offset:end_offset]));
p := parser.Parser {
err = parser_warning_handler, //empty
@@ -2382,7 +2375,9 @@ fallback_position_context_completion :: proc(document: ^Document, position: comm
e := parser.parse_expr(&p, true);
- if empty_dot {
+ //log.error(e.derived);
+
+ if empty_dot || empty_arrow {
position_context.selector = e;
}
diff --git a/src/server/completion.odin b/src/server/completion.odin
index 44ca8d5..a57acb5 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -219,6 +219,8 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc
}
+ //else if selector, ok := position_context.selector.
+
symbols := make([dynamic] index.Symbol, context.temp_allocator);
selector: index.Symbol;
@@ -230,8 +232,6 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc
selector, ok = resolve_type_expression(ast_context, position_context.selector);
if !ok {
- log.info(position_context.selector.derived);
- log.error("Failed to resolve type selector in completion list");
return;
}
@@ -265,27 +265,6 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc
#partial switch v in selector.value {
- /*
- case index.SymbolBitSetValue:
- list.isIncomplete = false;
-
- if elem, ok := resolve_type_expression(ast_context, v.expr); ok {
-
- if enum_value, ok := elem.value.(index.SymbolEnumValue); ok {
-
- for name in enum_value.names {
- symbol: index.Symbol;
- symbol.name = name;
- symbol.pkg = selector.name;
- symbol.type = .EnumMember;
- append(&symbols, symbol);
- }
-
- }
-
- }
- */
-
case index.SymbolBitFieldValue:
list.isIncomplete = false;
@@ -323,6 +302,19 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc
}
if symbol, ok := resolve_type_expression(ast_context, v.types[i]); ok {
+
+ if expr, ok := position_context.selector.derived.(ast.Selector_Expr); ok {
+
+ if expr.op.text == "->" && symbol.type != .Function {
+ continue;
+ }
+
+ }
+
+ if position_context.arrow && symbol.type != .Function {
+ continue;
+ }
+
symbol.name = name;
symbol.type = .Field;
symbol.pkg = selector.name;
@@ -345,8 +337,6 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc
list.isIncomplete = true;
- log.infof("search field %v, pkg %v", field, selector.pkg);
-
if searched, ok := index.fuzzy_search(field, {selector.pkg}); ok {
for search in searched {
@@ -360,48 +350,6 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc
return;
}
-
- case index.SymbolGenericValue:
-
- list.isIncomplete = false;
-
- if ptr, ok := v.expr.derived.(ast.Pointer_Type); ok {
-
- if symbol, ok := resolve_type_expression(ast_context, ptr.elem); ok {
-
- #partial switch s in symbol.value {
- case index.SymbolStructValue:
- for name, i in s.names {
- //ERROR no completion on name
-
- if selector.pkg != "" {
- ast_context.current_package = selector.pkg;
- }
-
- else {
- ast_context.current_package = ast_context.document_package;
- }
-
- if symbol, ok := resolve_type_expression(ast_context, s.types[i]); ok {
- symbol.name = name;
- symbol.type = .Field;
- symbol.pkg = symbol.name;
- symbol.signature = index.node_to_string(s.types[i]);
- append(&symbols, symbol);
- }
-
- else {
- symbol: index.Symbol;
- symbol.name = name;
- symbol.type = .Field;
- append(&symbols, symbol);
- }
- }
- }
- }
-
- }
-
}
for symbol, i in symbols {
@@ -804,9 +752,8 @@ get_identifier_completion :: proc(ast_context: ^AstContext, position_context: ^D
ast_context.use_globals = true;
ast_context.current_package = ast_context.document_package;
- last_local := v[len(v)-1];
- ident := index.new_type(ast.Ident, last_local.expr.pos, last_local.expr.end, context.temp_allocator);
+ ident := index.new_type(ast.Ident, { offset = position_context.position }, { offset = position_context.position }, context.temp_allocator);
ident.name = k;
if symbol, ok := resolve_type_identifier(ast_context, ident^); ok {
@@ -864,3 +811,9 @@ get_identifier_completion :: proc(ast_context: ^AstContext, position_context: ^D
list.items = items[:];
}
+get_package_completion :: proc(ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) {
+
+
+
+
+} \ No newline at end of file
diff --git a/src/server/requests.odin b/src/server/requests.odin
index 30bd262..d4e3cb3 100644
--- a/src/server/requests.odin
+++ b/src/server/requests.odin
@@ -480,7 +480,7 @@ request_initialize :: proc(task: ^common.Task) {
config.signature_offset_support = initialize_params.capabilities.textDocument.signatureHelp.signatureInformation.parameterInformation.labelOffsetSupport;
- completionTriggerCharacters := [] string { "." };
+ completionTriggerCharacters := [] string { ".", ">", "#" };
signatureTriggerCharacters := [] string { "(" };
token_type := type_info_of(SemanticTokenTypes).variant.(runtime.Type_Info_Named).base.variant.(runtime.Type_Info_Enum);