diff options
| author | Daniel Gavin <danielgavin5@hotmail.com> | 2021-05-06 17:08:07 +0200 |
|---|---|---|
| committer | Daniel Gavin <danielgavin5@hotmail.com> | 2021-05-06 17:08:07 +0200 |
| commit | 126553d5efff75d87c1a1505a42e922b5d13e9a9 (patch) | |
| tree | 469579cb3d9a0783e4efd5230748da1b52194fb4 /src | |
| parent | 9007c6fa37dff74c8abe2555f9da0420f0a81294 (diff) | |
started lazy creating signatures for procedures
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/ast.odin | 182 | ||||
| -rw-r--r-- | src/index/collector.odin | 11 | ||||
| -rw-r--r-- | src/index/util.odin | 169 | ||||
| -rw-r--r-- | src/server/analysis.odin | 10 | ||||
| -rw-r--r-- | src/server/completion.odin | 6 | ||||
| -rw-r--r-- | src/server/hover.odin | 2 | ||||
| -rw-r--r-- | src/server/signature.odin | 59 |
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, |