diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/references/ReferencesUtil.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/references/ReferencesUtil.java index 622d0601548d..5e64c7abe5a6 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/references/ReferencesUtil.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/references/ReferencesUtil.java @@ -17,6 +17,7 @@ import io.ballerina.compiler.api.SemanticModel; import io.ballerina.compiler.api.symbols.Symbol; +import io.ballerina.compiler.syntax.tree.ModulePartNode; import io.ballerina.compiler.syntax.tree.NonTerminalNode; import io.ballerina.compiler.syntax.tree.SyntaxKind; import io.ballerina.projects.Document; @@ -24,6 +25,7 @@ import io.ballerina.projects.Project; import io.ballerina.tools.diagnostics.Location; import io.ballerina.tools.text.LinePosition; +import io.ballerina.tools.text.TextRange; import org.ballerinalang.langserver.common.utils.CommonUtil; import org.ballerinalang.langserver.common.utils.PathUtil; import org.ballerinalang.langserver.common.utils.PositionUtil; @@ -120,7 +122,22 @@ public static Optional getSymbolAtCursor(PositionedOperationContext cont return Optional.empty(); } + Document document = srcFile.get(); Position position = context.getCursorPosition(); + TextRange range = TextRange.from( + document.textDocument().textPositionFrom(PositionUtil.getLinePosition(position)), 0); + NonTerminalNode nonTerminalNode = ((ModulePartNode) document.syntaxTree().rootNode()).findNode(range); + SyntaxKind parentKind = nonTerminalNode.parent().kind(); + + if (parentKind == SyntaxKind.TYPE_PARAMETER || parentKind == SyntaxKind.STREAM_TYPE_PARAMS) { + if (nonTerminalNode.lineRange().endLine().offset() == position.getCharacter()) { + // When there is a type parameter and cursor is at the end of the type parameter, semantic API does not + // provide the correct symbol. Therefore, here we search for the symbol at (col - 1). + return semanticModel.get().symbol(document, + LinePosition.from(position.getLine(), position.getCharacter() - 1)); + } + } + Optional symbolAtCursor = semanticModel.get().symbol(srcFile.get(), LinePosition.from(position.getLine(), position.getCharacter())); diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/definition/DefinitionTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/definition/DefinitionTest.java index 08c7780bbfee..892cafafd8af 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/definition/DefinitionTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/definition/DefinitionTest.java @@ -151,7 +151,8 @@ protected Object[][] testDataProvider() throws IOException { {"def_annotation_on_obj_func_config1.json", "project"}, {"def_typereference.json", "project"}, {"def_typereference2.json", "project"}, - {"def_typereference3.json", "project"} + {"def_typereference3.json", "project"}, + {"defProject15.json", "project"}, }; } diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/ProjectRenameTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/ProjectRenameTest.java index 12c0e2b5d647..cf490722901b 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/ProjectRenameTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/ProjectRenameTest.java @@ -54,6 +54,7 @@ private Object[][] testDataProvider() { // Negative/invalid cases {"rename_keyword_result1.json", "kw"}, {"rename_invalid_token_result1.json", "token"}, + {"rename_table_row_type_and_stream_type.json", "Student"}, }; } diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/RenameTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/RenameTest.java index ddbe2bb71462..11923e7911f8 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/RenameTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/RenameTest.java @@ -77,6 +77,12 @@ public Object[][] testDataProvider() { {"rename_self.json", "this"}, {"rename_invalid_qname_ref.json", "io"}, // {"rename_resource_method_path_segment.json", "path1"} //TODO: Fix #41041 + + {"rename_table_row_type_parameter1.json", "Student"}, + {"rename_table_row_type_parameter2.json", "Student"}, + {"rename_table_row_type_parameter3.json", "Student"}, + {"rename_stream_type_parameter.json", "Student"}, + {"rename_map_type_parameter.json", "Student"}, }; } } diff --git a/language-server/modules/langserver-core/src/test/resources/definition/expected/project/defProject15.json b/language-server/modules/langserver-core/src/test/resources/definition/expected/project/defProject15.json new file mode 100644 index 000000000000..abe51a94884d --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/definition/expected/project/defProject15.json @@ -0,0 +1,24 @@ +{ + "source": { + "file": "projectls/defmodsource6.bal" + }, + "position": { + "line": 3, + "character": 19 + }, + "result": [ + { + "range": { + "start": { + "line": 9, + "character": 12 + }, + "end": { + "line": 9, + "character": 17 + } + }, + "uri": "projectls/modules/lsmod3/lsmod3.bal" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/defmodsource6.bal b/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/defmodsource6.bal new file mode 100644 index 000000000000..c002065b5d3c --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/defmodsource6.bal @@ -0,0 +1,6 @@ +import projectls.lsmod3; + +function foo() { + table tHuman = table [{id: 1, name: "Jane"}]; +} + diff --git a/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/modules/lsmod3/lsmod3.bal b/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/modules/lsmod3/lsmod3.bal index 81f65bb8da58..e210999d68fb 100644 --- a/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/modules/lsmod3/lsmod3.bal +++ b/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/modules/lsmod3/lsmod3.bal @@ -6,3 +6,8 @@ public function mod3Function1() { public type MyType lsmod1:MyType; public type MyType2 MyType; + +public type Human record {| + readonly int id; + string name; +|}; diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/project/rename_table_row_type_and_stream_type.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/project/rename_table_row_type_and_stream_type.json new file mode 100644 index 000000000000..85b26cc4f006 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/project/rename_table_row_type_and_stream_type.json @@ -0,0 +1,54 @@ +{ + "source": { + "file": "main.bal" + }, + "position": { + "line": 19, + "character": 23 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "modules/module2/types.bal": [{ + "range": { + "start": { + "line": 2, + "character": 12 + }, + "end": { + "line": 2, + "character": 17 + } + }, + "newText": "Student" + }], + "main.bal": [{ + "range": { + "start": { + "line": 18, + "character": 19 + }, + "end": { + "line": 18, + "character": 24 + } + }, + "newText": "Student" + }, { + "range": { + "start": { + "line": 19, + "character": 18 + }, + "end": { + "line": 19, + "character": 23 + } + }, + "newText": "Student" + }] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_map_type_parameter.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_map_type_parameter.json new file mode 100644 index 000000000000..7d2f8265f1c3 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_map_type_parameter.json @@ -0,0 +1,44 @@ +{ + "source": { + "file": "rename_map_type_parameter.bal" + }, + "position": { + "line": 6, + "character": 14 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_map_type_parameter.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 8 + }, + "end": { + "line": 6, + "character": 14 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_stream_type_parameter.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_stream_type_parameter.json new file mode 100644 index 000000000000..f08f38ba0b68 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_stream_type_parameter.json @@ -0,0 +1,57 @@ +{ + "source": { + "file": "rename_stream_type_parameter.bal" + }, + "position": { + "line": 7, + "character": 17 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_stream_type_parameter.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 10 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 7, + "character": 11 + }, + "end": { + "line": 7, + "character": 17 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter1.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter1.json new file mode 100644 index 000000000000..33a03123149c --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter1.json @@ -0,0 +1,44 @@ +{ + "source": { + "file": "rename_table_row_type_parameter1.bal" + }, + "position": { + "line": 6, + "character": 16 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_table_row_type_parameter1.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 10 + }, + "end": { + "line": 6, + "character": 16 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter2.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter2.json new file mode 100644 index 000000000000..e0c14a558e61 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter2.json @@ -0,0 +1,70 @@ +{ + "source": { + "file": "rename_table_row_type_parameter2.bal" + }, + "position": { + "line": 7, + "character": 16 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_table_row_type_parameter2.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 10 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 7, + "character": 10 + }, + "end": { + "line": 7, + "character": 16 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 8, + "character": 11 + }, + "end": { + "line": 8, + "character": 17 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter3.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter3.json new file mode 100644 index 000000000000..70ebeacb467a --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter3.json @@ -0,0 +1,44 @@ +{ + "source": { + "file": "rename_table_row_type_parameter1.bal" + }, + "position": { + "line": 6, + "character": 13 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_table_row_type_parameter1.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 10 + }, + "end": { + "line": 6, + "character": 16 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/project/main.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/project/main.bal index 4c143350cad3..816fd0bcd572 100644 --- a/language-server/modules/langserver-core/src/test/resources/rename/sources/project/main.bal +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/project/main.bal @@ -15,4 +15,7 @@ public function main() { int localInt = module1:gInt; module2:setName(fname = "John", lname = "Doe"); + + stream s = new; + table tHuman = table [{id: 1, name: "Jane"}]; } diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/project/modules/module2/types.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/project/modules/module2/types.bal index e267324e7d5f..c03e271fb9e7 100644 --- a/language-server/modules/langserver-core/src/test/resources/rename/sources/project/modules/module2/types.bal +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/project/modules/module2/types.bal @@ -1 +1,6 @@ public type Mod1Error error; + +public type Human record {| + readonly int id; + string name; +|}; diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_map_type_parameter.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_map_type_parameter.bal new file mode 100644 index 000000000000..04dace1d2832 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_map_type_parameter.bal @@ -0,0 +1,8 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + map m = new; +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_stream_type_parameter.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_stream_type_parameter.bal new file mode 100644 index 000000000000..8bd2017f31d4 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_stream_type_parameter.bal @@ -0,0 +1,9 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + Person p = { id: 1, name: "foo" }; + stream s = new; +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter1.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter1.bal new file mode 100644 index 000000000000..2c2d75d578ef --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter1.bal @@ -0,0 +1,8 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + table tHuman = table [{id: 1, name: "Jane"}]; +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter2.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter2.bal new file mode 100644 index 000000000000..14931acdb3b9 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter2.bal @@ -0,0 +1,10 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + Person p = { id: 1, name: "foo" }; + table tHuman = table [{id: 1, name: "Jane"}]; + stream s = new; +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter3.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter3.bal new file mode 100644 index 000000000000..2c2d75d578ef --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter3.bal @@ -0,0 +1,8 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + table tHuman = table [{id: 1, name: "Jane"}]; +}