aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2021-05-05 23:43:12 +0200
committerDaniel Gavin <danielgavin5@hotmail.com>2021-05-05 23:43:12 +0200
commit28ce0ddfebfd671094e8da231923ff96fb72dd47 (patch)
tree62505e3c9959b3c41ef9f1580702679d92f668a7
parentd25e7a8dfd64e492e4fe23876f2ccc646ed18c57 (diff)
begun argument underlining
-rw-r--r--src/server/analysis.odin28
-rw-r--r--src/server/signature.odin50
-rw-r--r--src/testing/testing.odin10
-rw-r--r--tests/completions_test.odin8
-rw-r--r--tests/signatures_test.odin38
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