diff options
| author | Daniel Gavin <danielgavin5@hotmail.com> | 2021-05-05 23:43:12 +0200 |
|---|---|---|
| committer | Daniel Gavin <danielgavin5@hotmail.com> | 2021-05-05 23:43:12 +0200 |
| commit | 28ce0ddfebfd671094e8da231923ff96fb72dd47 (patch) | |
| tree | 62505e3c9959b3c41ef9f1580702679d92f668a7 | |
| parent | d25e7a8dfd64e492e4fe23876f2ccc646ed18c57 (diff) | |
begun argument underlining
| -rw-r--r-- | src/server/analysis.odin | 28 | ||||
| -rw-r--r-- | src/server/signature.odin | 50 | ||||
| -rw-r--r-- | src/testing/testing.odin | 10 | ||||
| -rw-r--r-- | tests/completions_test.odin | 8 | ||||
| -rw-r--r-- | tests/signatures_test.odin | 38 |
5 files changed, 129 insertions, 5 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin index cd505ce..d7ac8ef 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -57,6 +57,7 @@ DocumentPositionContext :: struct { hint: DocumentPositionContextHint, global_lhs_stmt: bool, import_stmt: ^ast.Import_Decl, + call_commas: []int, } DocumentLocal :: struct { @@ -2285,6 +2286,29 @@ get_document_symbols :: proc(document: ^Document) -> []DocumentSymbol { } /* + Parser gives ranges of expression, but not actually where the commas are placed. +*/ +get_call_commas :: proc(position_context: ^DocumentPositionContext, document: ^Document) { + + if position_context.call == nil { + return; + } + + commas := make([dynamic]int, 0, 10, context.temp_allocator); + + if call, ok := position_context.call.derived.(ast.Call_Expr); ok { + for i := call.open.offset; i < call.close.offset; i += 1 { + + if document.text[i] == ',' { + append(&commas, i); + } + } + } + + position_context.call_commas = commas[:]; +} + +/* Figure out what exactly is at the given position and whether it is in a function, struct, etc. */ get_document_position_context :: proc(document: ^Document, position: common.Position, hint: DocumentPositionContextHint) -> (DocumentPositionContext, bool) { @@ -2357,6 +2381,10 @@ get_document_position_context :: proc(document: ^Document, position: common.Posi fallback_position_context_signature(document, position, &position_context); } + if hint == .SignatureHelp { + get_call_commas(&position_context, document); + } + return position_context, true; } diff --git a/src/server/signature.odin b/src/server/signature.odin index 883bd2e..64028c8 100644 --- a/src/server/signature.odin +++ b/src/server/signature.odin @@ -16,7 +16,36 @@ import "core:slice" import "shared:common" import "shared:index" - +SignatureInformationCapabilities :: struct { + parameterInformation: ParameterInformationCapabilities, +} + +SignatureHelpClientCapabilities :: struct { + dynamicRegistration: bool, + signatureInformation: SignatureInformationCapabilities, + contextSupport: bool, +} + +SignatureHelpOptions :: struct { + triggerCharacters: []string, + retriggerCharacters: []string, +} + +SignatureHelp :: struct { + signatures: []SignatureInformation, + activeSignature: int, + activeParameter: int, +} + +SignatureInformation :: struct { + label: string, + documentation: string, + parameters: []ParameterInformation, +} + +ParameterInformation :: struct { + label: string, +} get_signature_information :: proc(document: ^Document, position: common.Position) -> (SignatureHelp, bool) { @@ -40,15 +69,30 @@ get_signature_information :: proc(document: ^Document, position: common.Position get_locals(document.ast, position_context.function, &ast_context, &position_context); } + for comma, i in position_context.call_commas { + if position_context.position > comma { + signature_help.activeParameter = i+1; + } else if position_context.position == comma { + signature_help.activeParameter = i; + } + } + call: index.Symbol; call, ok = resolve_type_expression(&ast_context, position_context.call); signature_information := make([dynamic]SignatureInformation, context.temp_allocator); - if _, ok := call.value.(index.SymbolProcedureValue); ok { + if value, ok := call.value.(index.SymbolProcedureValue); ok { + 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); + } + info := SignatureInformation { label = concatenate_symbols_information(&ast_context, call, false), documentation = call.doc, + parameters = parameters, }; append(&signature_information, info); } else if value, ok := call.value.(index.SymbolAggregateValue); ok { @@ -62,8 +106,6 @@ get_signature_information :: proc(document: ^Document, position: common.Position } signature_help.signatures = signature_information[:]; - signature_help.activeSignature = 0; - signature_help.activeParameter = 0; return signature_help, true; }
\ No newline at end of file diff --git a/src/testing/testing.odin b/src/testing/testing.odin index e74fb0e..7b30e93 100644 --- a/src/testing/testing.odin +++ b/src/testing/testing.odin @@ -145,6 +145,16 @@ expect_signature_labels :: proc(t: ^testing.T, src: ^Source, expect_labels: []st } +expect_signature_parameter_position :: proc(t: ^testing.T, src: ^Source, position: int) { + setup(src); + + help, ok := server.get_signature_information(src.document, src.position); + + if help.activeParameter != position { + testing.errorf(t, "expected parameter position %v, but received %v", position, help.activeParameter); + } +} + expect_completion_details :: proc(t: ^testing.T, src: ^Source, trigger_character: string, expect_details: []string) { setup(src); diff --git a/tests/completions_test.odin b/tests/completions_test.odin index 59e58ab..d346547 100644 --- a/tests/completions_test.odin +++ b/tests/completions_test.odin @@ -321,4 +321,12 @@ ast_package_completion :: proc(t: ^testing.T) { resolveProvider?: boolean; } +*/ + +/* + position_context.last_token = tokenizer.Token { + kind = .Comma, + }; + + It shows the type instead of the label Token_Kind */
\ No newline at end of file diff --git a/tests/signatures_test.odin b/tests/signatures_test.odin index d5c9da2..ed4392a 100644 --- a/tests/signatures_test.odin +++ b/tests/signatures_test.odin @@ -38,6 +38,42 @@ ast_simple_proc_signature :: proc(t: ^testing.T) { } @(test) +ast_proc_signature_argument_position :: proc(t: ^testing.T) { + + source := test.Source { + main = `package test + cool_function :: proc(a: int, b: int) { + } + + main :: proc() { + cool_function(2,* + } + `, + packages = {}, + }; + + test.expect_signature_parameter_position(t, &source, 1); +} + +@(test) +ast_proc_signature_argument_move_position :: proc(t: ^testing.T) { + + source := test.Source { + main = `package test + cool_function :: proc(a: int, b: int, c: int) { + } + + main :: proc() { + cool_function(2,*, 3); + } + `, + packages = {}, + }; + + test.expect_signature_parameter_position(t, &source, 1); +} + +@(test) ast_proc_group_signature_empty_call :: proc(t: ^testing.T) { source := test.Source { @@ -182,4 +218,4 @@ ast_proc_group_signature_struct :: proc(t: ^testing.T) { }; test.expect_signature_labels(t, &source, {"test.struct_function: proc(a: int, b: My_Struct, c: int)"}); -} +}
\ No newline at end of file |