aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2021-05-06 17:08:07 +0200
committerDaniel Gavin <danielgavin5@hotmail.com>2021-05-06 17:08:07 +0200
commit126553d5efff75d87c1a1505a42e922b5d13e9a9 (patch)
tree469579cb3d9a0783e4efd5230748da1b52194fb4 /src
parent9007c6fa37dff74c8abe2555f9da0420f0a81294 (diff)
started lazy creating signatures for procedures
Diffstat (limited to 'src')
-rw-r--r--src/common/ast.odin182
-rw-r--r--src/index/collector.odin11
-rw-r--r--src/index/util.odin169
-rw-r--r--src/server/analysis.odin10
-rw-r--r--src/server/completion.odin6
-rw-r--r--src/server/hover.odin2
-rw-r--r--src/server/signature.odin59
7 files changed, 246 insertions, 193 deletions
diff --git a/src/common/ast.odin b/src/common/ast.odin
index 0c9bdcf..dfc603b 100644
--- a/src/common/ast.odin
+++ b/src/common/ast.odin
@@ -5,6 +5,7 @@ import "core:log"
import "core:mem"
import "core:fmt"
import "core:strings"
+import "core:path"
keyword_map: map[string]bool = {
"int" = true,
@@ -622,3 +623,184 @@ node_equal_node :: proc(a, b: ^ast.Node) -> bool {
return false;
}
+
+/*
+ Returns the string representation of a type. This allows us to print the signature without storing it in the indexer as a string(saving memory).
+*/
+node_to_string :: proc(node: ^ast.Node) -> string {
+
+ builder := strings.make_builder(context.temp_allocator);
+
+ build_string(node, &builder);
+
+ return strings.to_string(builder);
+}
+
+build_string :: proc{
+ build_string_ast_array,
+ build_string_dynamic_array,
+ build_string_node,
+};
+
+build_string_dynamic_array :: proc(array: $A/[]^$T, builder: ^strings.Builder) {
+
+ for elem, i in array {
+ build_string(elem, builder);
+ }
+}
+
+build_string_ast_array :: proc(array: $A/[dynamic]^$T, builder: ^strings.Builder) {
+
+ for elem, i in array {
+ build_string(elem, builder);
+ }
+}
+
+build_string_node :: proc(node: ^ast.Node, builder: ^strings.Builder) {
+
+ using ast;
+
+ if node == nil {
+ return;
+ }
+
+ switch n in node.derived {
+ case Bad_Expr:
+ case Ident:
+ if strings.contains(n.name, "/") {
+ strings.write_string(builder, path.base(n.name, false, context.temp_allocator));
+ } else {
+ strings.write_string(builder, n.name);
+ }
+ case Implicit:
+ strings.write_string(builder, n.tok.text);
+ case Undef:
+ case Basic_Lit:
+ strings.write_string(builder, n.tok.text);
+ case Basic_Directive:
+ strings.write_string(builder, n.name);
+ case Ellipsis:
+ build_string(n.expr, builder);
+ case Proc_Lit:
+ build_string(n.type, builder);
+ build_string(n.body, builder);
+ case Comp_Lit:
+ build_string(n.type, builder);
+ build_string(n.elems, builder);
+ case Tag_Expr:
+ build_string(n.expr, builder);
+ case Unary_Expr:
+ build_string(n.expr, builder);
+ case Binary_Expr:
+ build_string(n.left, builder);
+ build_string(n.right, builder);
+ case Paren_Expr:
+ strings.write_string(builder, "(");
+ build_string(n.expr, builder);
+ strings.write_string(builder, ")");
+ case Call_Expr:
+ build_string(n.expr, builder);
+ strings.write_string(builder, "(");
+ build_string(n.args, builder);
+ strings.write_string(builder, ")");
+ case Selector_Expr:
+ build_string(n.expr, builder);
+ strings.write_string(builder, ".");
+ build_string(n.field, builder);
+ case Index_Expr:
+ build_string(n.expr, builder);
+ strings.write_string(builder, "[");
+ build_string(n.index, builder);
+ strings.write_string(builder, "]");
+ case Deref_Expr:
+ build_string(n.expr, builder);
+ case Slice_Expr:
+ build_string(n.expr, builder);
+ build_string(n.low, builder);
+ build_string(n.high, builder);
+ case Field_Value:
+ build_string(n.field, builder);
+ strings.write_string(builder, ": ");
+ build_string(n.value, builder);
+ case Type_Cast:
+ build_string(n.type, builder);
+ build_string(n.expr, builder);
+ case Bad_Stmt:
+ case Bad_Decl:
+ case Attribute:
+ build_string(n.elems, builder);
+ case Field:
+ build_string(n.names, builder);
+ if len(n.names) > 0 && n.type != nil {
+ strings.write_string(builder, ": ");
+ build_string(n.type, builder);
+
+ if n.default_value != nil && n.type != nil {
+ strings.write_string(builder, "=");
+ }
+
+ } else if len(n.names) > 0 && n.default_value != nil {
+ strings.write_string(builder, " := ");
+ }
+
+ build_string(n.default_value, builder);
+ case Field_List:
+ for field, i in n.list {
+ build_string(field, builder);
+ if len(n.list) - 1 != i {
+ strings.write_string(builder, ",");
+ }
+ }
+ case Typeid_Type:
+ build_string(n.specialization, builder);
+ case Helper_Type:
+ build_string(n.type, builder);
+ case Distinct_Type:
+ build_string(n.type, builder);
+ case Poly_Type:
+ strings.write_string(builder, "$");
+
+ build_string(n.type, builder);
+
+ if n.specialization != nil {
+ strings.write_string(builder, "/");
+ build_string(n.specialization, builder);
+ }
+ case Proc_Type:
+ strings.write_string(builder, "proc(");
+ build_string(n.params, builder);
+ strings.write_string(builder, ") -> ");
+ build_string(n.results, builder);
+ case Pointer_Type:
+ strings.write_string(builder, "^");
+ build_string(n.elem, builder);
+ case Array_Type:
+ strings.write_string(builder, "[");
+ build_string(n.len, builder);
+ strings.write_string(builder, "]");
+ build_string(n.elem, builder);
+ case Dynamic_Array_Type:
+ strings.write_string(builder, "[dynamic]");
+ build_string(n.elem, builder);
+ case Struct_Type:
+ build_string(n.poly_params, builder);
+ build_string(n.align, builder);
+ build_string(n.fields, builder);
+ case Union_Type:
+ build_string(n.poly_params, builder);
+ build_string(n.align, builder);
+ build_string(n.variants, builder);
+ case Enum_Type:
+ build_string(n.base_type, builder);
+ build_string(n.fields, builder);
+ case Bit_Set_Type:
+ build_string(n.elem, builder);
+ build_string(n.underlying, builder);
+ case Map_Type:
+ strings.write_string(builder, "map");
+ strings.write_string(builder, "[");
+ build_string(n.key, builder);
+ strings.write_string(builder, "]");
+ build_string(n.value, builder);
+ }
+}
diff --git a/src/index/collector.odin b/src/index/collector.odin
index 053c27e..952b0cb 100644
--- a/src/index/collector.odin
+++ b/src/index/collector.odin
@@ -304,17 +304,6 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri
case ast.Proc_Type:
token = v;
token_type = .Function;
-
- if v.params != nil {
- symbol.signature = strings.concatenate({"(", string(file.src[v.params.pos.offset:v.params.end.offset]), ")"},
- collection.allocator);
- }
-
- if v.results != nil {
- symbol.returns = strings.concatenate({"(", string(file.src[v.results.pos.offset:v.results.end.offset]), ")"},
- collection.allocator);
- }
-
symbol.value = collect_procedure_fields(collection, cast(^ast.Proc_Type)col_expr, v.params, v.results, package_map);
case ast.Proc_Group:
token = v;
diff --git a/src/index/util.odin b/src/index/util.odin
deleted file mode 100644
index e87af2b..0000000
--- a/src/index/util.odin
+++ /dev/null
@@ -1,169 +0,0 @@
-package index
-
-import "core:odin/ast"
-import "core:strings"
-import "core:path"
-
-/*
- Returns the string representation of a type. This allows us to print the signature without storing it in the indexer as a string(saving memory).
-*/
-node_to_string :: proc(node: ^ast.Node) -> string {
-
- builder := strings.make_builder(context.temp_allocator);
-
- build_string(node, &builder);
-
- return strings.to_string(builder);
-}
-
-build_string :: proc{
- build_string_ast_array,
- build_string_dynamic_array,
- build_string_node,
-};
-
-build_string_dynamic_array :: proc(array: $A/[]^$T, builder: ^strings.Builder) {
-
- for elem, i in array {
- build_string(elem, builder);
- }
-}
-
-build_string_ast_array :: proc(array: $A/[dynamic]^$T, builder: ^strings.Builder) {
-
- for elem, i in array {
- build_string(elem, builder);
- }
-}
-
-build_string_node :: proc(node: ^ast.Node, builder: ^strings.Builder) {
-
- using ast;
-
- if node == nil {
- return;
- }
-
- switch n in node.derived {
- case Bad_Expr:
- case Ident:
- if strings.contains(n.name, "/") {
- strings.write_string(builder, path.base(n.name, false, context.temp_allocator));
- } else {
- strings.write_string(builder, n.name);
- }
- case Implicit:
- case Undef:
- case Basic_Lit:
- //strings.write_string(builder, n.tok.text);
- case Ellipsis:
- build_string(n.expr, builder);
- case Proc_Lit:
- build_string(n.type, builder);
- build_string(n.body, builder);
- case Comp_Lit:
- build_string(n.type, builder);
- build_string(n.elems, builder);
- case Tag_Expr:
- build_string(n.expr, builder);
- case Unary_Expr:
- build_string(n.expr, builder);
- case Binary_Expr:
- build_string(n.left, builder);
- build_string(n.right, builder);
- case Paren_Expr:
- strings.write_string(builder, "(");
- build_string(n.expr, builder);
- strings.write_string(builder, ")");
- case Call_Expr:
- build_string(n.expr, builder);
- strings.write_string(builder, "(");
- build_string(n.args, builder);
- strings.write_string(builder, ")");
- case Selector_Expr:
- build_string(n.expr, builder);
- strings.write_string(builder, ".");
- build_string(n.field, builder);
- case Index_Expr:
- build_string(n.expr, builder);
- strings.write_string(builder, "[");
- build_string(n.index, builder);
- strings.write_string(builder, "]");
- case Deref_Expr:
- build_string(n.expr, builder);
- case Slice_Expr:
- build_string(n.expr, builder);
- build_string(n.low, builder);
- build_string(n.high, builder);
- case Field_Value:
- build_string(n.field, builder);
- strings.write_string(builder, ": ");
- build_string(n.value, builder);
- case Type_Cast:
- build_string(n.type, builder);
- build_string(n.expr, builder);
- case Bad_Stmt:
- case Bad_Decl:
- case Attribute:
- build_string(n.elems, builder);
- case Field:
- build_string(n.names, builder);
- if len(n.names) > 0 {
- strings.write_string(builder, ": ");
- }
- build_string(n.type, builder);
- build_string(n.default_value, builder);
- case Field_List:
- for field, i in n.list {
- build_string(field, builder);
- if len(n.list) - 1 != i {
- strings.write_string(builder, ",");
- }
- }
- case Typeid_Type:
- build_string(n.specialization, builder);
- case Helper_Type:
- build_string(n.type, builder);
- case Distinct_Type:
- build_string(n.type, builder);
- case Poly_Type:
- build_string(n.type, builder);
- build_string(n.specialization, builder);
- case Proc_Type:
- strings.write_string(builder, "proc(");
- build_string(n.params, builder);
- strings.write_string(builder, ") -> ");
- build_string(n.results, builder);
- case Pointer_Type:
- strings.write_string(builder, "^");
- build_string(n.elem, builder);
- case Array_Type:
- strings.write_string(builder, "[");
- build_string(n.len, builder);
- strings.write_string(builder, "]");
- build_string(n.elem, builder);
- case Dynamic_Array_Type:
- strings.write_string(builder, "[dynamic]");
- build_string(n.elem, builder);
- case Struct_Type:
- build_string(n.poly_params, builder);
- build_string(n.align, builder);
- build_string(n.fields, builder);
- case Union_Type:
- build_string(n.poly_params, builder);
- build_string(n.align, builder);
- build_string(n.variants, builder);
- case Enum_Type:
- build_string(n.base_type, builder);
- build_string(n.fields, builder);
- case Bit_Set_Type:
- build_string(n.elem, builder);
- build_string(n.underlying, builder);
- case Map_Type:
- strings.write_string(builder, "map");
- strings.write_string(builder, "[");
- build_string(n.key, builder);
- strings.write_string(builder, "]");
- build_string(n.value, builder);
- }
-}
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index d7ac8ef..7cd4764 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -1365,21 +1365,15 @@ make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, v
arg_types := make([dynamic]^ast.Field, context.temp_allocator);
if v.results != nil {
-
for ret in v.results.list {
append(&return_types, ret);
}
-
- symbol.returns = strings.concatenate({"(", string(ast_context.file.src[v.results.pos.offset:v.results.end.offset]), ")"}, context.temp_allocator);
}
if v.params != nil {
-
for param in v.params.list {
append(&arg_types, param);
}
-
- symbol.signature = strings.concatenate({"(", string(ast_context.file.src[v.params.pos.offset:v.params.end.offset]), ")"}, context.temp_allocator);
}
symbol.value = index.SymbolProcedureValue {
@@ -2202,7 +2196,7 @@ get_signature :: proc(ast_context: ^AstContext, ident: ast.Ident, symbol: index.
if i, ok := local.derived.(ast.Ident); ok {
return get_signature(ast_context, i, symbol, true);
} else {
- return index.node_to_string(local);
+ return common.node_to_string(local);
}
}
@@ -2210,7 +2204,7 @@ get_signature :: proc(ast_context: ^AstContext, ident: ast.Ident, symbol: index.
if i, ok := global.expr.derived.(ast.Ident); ok {
return get_signature(ast_context, i, symbol, true);
} else {
- return index.node_to_string(global.expr);
+ return common.node_to_string(global.expr);
}
}
}
diff --git a/src/server/completion.odin b/src/server/completion.odin
index 66893e0..241548d 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -231,7 +231,7 @@ get_comp_lit_completion :: proc(ast_context: ^AstContext, position_context: ^Doc
item := CompletionItem {
label = resolved.name,
kind = .Field,
- detail = fmt.tprintf("%v.%v: %v", comp_symbol.name, resolved.name, index.node_to_string(v.types[i])),
+ detail = fmt.tprintf("%v.%v: %v", comp_symbol.name, resolved.name, common.node_to_string(v.types[i])),
documentation = resolved.doc,
};
@@ -364,7 +364,7 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc
item := CompletionItem {
label = name,
kind = .Field,
- detail = fmt.tprintf("%v.%v: %v", selector.name, name, index.node_to_string(v.types[i])),
+ detail = fmt.tprintf("%v.%v: %v", selector.name, name, common.node_to_string(v.types[i])),
documentation = symbol.doc,
};
@@ -374,7 +374,7 @@ get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^Doc
item := CompletionItem {
label = symbol.name,
kind = .Field,
- detail = fmt.tprintf("%v: %v", name, index.node_to_string(v.types[i])),
+ detail = fmt.tprintf("%v: %v", name, common.node_to_string(v.types[i])),
documentation = symbol.doc,
};
diff --git a/src/server/hover.odin b/src/server/hover.odin
index d14cd34..771c867 100644
--- a/src/server/hover.odin
+++ b/src/server/hover.odin
@@ -126,7 +126,7 @@ get_hover_information :: proc(document: ^Document, position: common.Position) ->
if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok {
symbol.name = name;
symbol.pkg = selector.name;
- symbol.signature = index.node_to_string(v.types[i]);
+ symbol.signature = common.node_to_string(v.types[i]);
hover.contents = write_hover_content(&ast_context, symbol);
return hover, true;
}
diff --git a/src/server/signature.odin b/src/server/signature.odin
index d084507..1c2f52f 100644
--- a/src/server/signature.odin
+++ b/src/server/signature.odin
@@ -47,6 +47,47 @@ ParameterInformation :: struct {
label: string,
}
+/*
+ Lazily build the signature and returns from ast.Nodes
+*/
+build_symbol_signature :: proc(symbol: ^index.Symbol) {
+ if value, ok := symbol.value.(index.SymbolProcedureValue); ok {
+ builder := strings.make_builder(context.temp_allocator);
+
+ strings.write_string(&builder, "(");
+ for arg, i in value.arg_types {
+ strings.write_string(&builder, common.node_to_string(arg));
+ if i != len(value.arg_types) - 1 {
+ strings.write_string(&builder, ", ");
+ }
+ }
+ strings.write_string(&builder, ")");
+
+ symbol.signature = strings.to_string(builder);
+ }
+}
+
+build_symbol_return :: proc(symbol: ^index.Symbol) {
+ if value, ok := symbol.value.(index.SymbolProcedureValue); ok {
+ builder := strings.make_builder(context.temp_allocator);
+
+ if len(value.return_types) == 0 {
+ return;
+ }
+
+ strings.write_string(&builder, "(");
+ for arg, i in value.return_types {
+ strings.write_string(&builder, common.node_to_string(arg));
+ if i != len(value.return_types) - 1 {
+ strings.write_string(&builder, ", ");
+ }
+ }
+ strings.write_string(&builder, ")");
+ symbol.returns = strings.to_string(builder);
+ }
+}
+
+
get_signature_information :: proc(document: ^Document, position: common.Position) -> (SignatureHelp, bool) {
signature_help: SignatureHelp;
@@ -88,9 +129,19 @@ get_signature_information :: proc(document: ^Document, position: common.Position
parameters := make([]ParameterInformation, len(value.arg_types), context.temp_allocator);
for arg, i in value.arg_types {
- parameters[i].label = common.get_ast_node_string(arg, document.ast.src);
+
+ if arg.type != nil {
+ if _, is_ellipsis := arg.type.derived.(ast.Ellipsis); is_ellipsis {
+ signature_help.activeParameter = min(i, signature_help.activeParameter);
+ }
+ }
+
+ parameters[i].label = common.node_to_string(arg);
}
+ build_symbol_signature(&call);
+ build_symbol_return(&call);
+
info := SignatureInformation {
label = concatenate_symbols_information(&ast_context, call, false),
documentation = call.doc,
@@ -100,6 +151,12 @@ get_signature_information :: proc(document: ^Document, position: common.Position
} else if value, ok := call.value.(index.SymbolAggregateValue); ok {
//function overloaded procedures
for symbol in value.symbols {
+
+ symbol := symbol;
+
+ build_symbol_signature(&call);
+ build_symbol_return(&call);
+
info := SignatureInformation {
label = concatenate_symbols_information(&ast_context, symbol, false),
documentation = symbol.doc,