From 77b09bb44c82c93c50959de2356ac567bf939c0b Mon Sep 17 00:00:00 2001 From: LakshanWeerasinghe Date: Wed, 19 Jul 2023 09:38:51 +0530 Subject: [PATCH 1/4] Fix field name resolving for immutable record type --- .../compiler/util/TypeDefBuilderHelper.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/TypeDefBuilderHelper.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/TypeDefBuilderHelper.java index 1f4ecde6dc7f..6f5627115351 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/TypeDefBuilderHelper.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/TypeDefBuilderHelper.java @@ -331,12 +331,13 @@ public static void populateStructureFields(Types types, SymbolTable symTable, fieldType = origField.type; } - Name origFieldName = origField.name; + Name origFieldName = origField.symbol.originalName; + Name fieldName = origField.name; BVarSymbol fieldSymbol; BType referredType = Types.getReferredType(fieldType); if (referredType.tag == TypeTags.INVOKABLE && referredType.tsymbol != null) { fieldSymbol = new BInvokableSymbol(origField.symbol.tag, origField.symbol.flags | flag, - origFieldName, pkgID, fieldType, + fieldName, origFieldName, pkgID, fieldType, structureSymbol, origField.symbol.pos, SOURCE); BInvokableTypeSymbol tsymbol = (BInvokableTypeSymbol) referredType.tsymbol; BInvokableSymbol invokableSymbol = (BInvokableSymbol) fieldSymbol; @@ -347,16 +348,16 @@ public static void populateStructureFields(Types types, SymbolTable symTable, } else if (fieldType == symTable.semanticError) { // Can only happen for records. fieldSymbol = new BVarSymbol(origField.symbol.flags | flag | Flags.OPTIONAL, - origFieldName, pkgID, symTable.neverType, + fieldName, origFieldName, pkgID, symTable.neverType, structureSymbol, origField.symbol.pos, SOURCE); } else { - fieldSymbol = new BVarSymbol(origField.symbol.flags | flag, origFieldName, pkgID, + fieldSymbol = new BVarSymbol(origField.symbol.flags | flag, fieldName, origFieldName, pkgID, fieldType, structureSymbol, origField.symbol.pos, SOURCE); } - String nameString = origFieldName.value; - fields.put(nameString, new BField(origFieldName, null, fieldSymbol)); - structureSymbol.scope.define(origFieldName, fieldSymbol); + String nameString = fieldName.value; + fields.put(nameString, new BField(fieldName, null, fieldSymbol)); + structureSymbol.scope.define(fieldName, fieldSymbol); } structureType.fields = fields; From 0139a96fee33da09cafd86aacd1d9eb6a8e4a6b9 Mon Sep 17 00:00:00 2001 From: LakshanWeerasinghe Date: Wed, 19 Jul 2023 10:17:25 +0530 Subject: [PATCH 2/4] Fix find exisiting record fields in RecordUtil --- .../org/ballerinalang/langserver/common/utils/RecordUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/RecordUtil.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/RecordUtil.java index 6613f3eb1ab0..87b34cf25f81 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/RecordUtil.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/RecordUtil.java @@ -186,7 +186,7 @@ public static String getFillAllRecordFieldInsertText(Map getRecordFields(RawTypeSymbolWrapper wrapper, List existingFields) { return wrapper.getRawType().fieldDescriptors().entrySet().stream() - .filter(e -> !existingFields.contains(e.getKey())) + .filter(e -> !existingFields.contains(e.getValue().getName().get())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } From 9ed5f105cce88ab0994e9cbcac2a89bfcded734a Mon Sep 17 00:00:00 2001 From: LakshanWeerasinghe Date: Wed, 19 Jul 2023 10:45:59 +0530 Subject: [PATCH 3/4] Add tests for fill record field code action --- .../FillRecordFieldsCodeActionTest.java | 7 ++++- .../config/fill_record_fields_config19.json | 30 +++++++++++++++++++ .../config/fill_record_fields_config20.json | 30 +++++++++++++++++++ .../config/fill_record_fields_config21.json | 30 +++++++++++++++++++ .../config/fill_record_fields_config22.json | 30 +++++++++++++++++++ .../config/fill_record_fields_config23.json | 30 +++++++++++++++++++ .../source/fill_record_fields_source16.bal | 29 ++++++++++++++++++ 7 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config19.json create mode 100644 language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config20.json create mode 100644 language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config21.json create mode 100644 language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config22.json create mode 100644 language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config23.json create mode 100644 language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/source/fill_record_fields_source16.bal diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/FillRecordFieldsCodeActionTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/FillRecordFieldsCodeActionTest.java index 98f02334e2d1..08a45f146364 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/FillRecordFieldsCodeActionTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/FillRecordFieldsCodeActionTest.java @@ -59,7 +59,12 @@ public Object[][] dataProvider() { {"fill_record_fields_config15.json"}, {"fill_record_fields_config16.json"}, {"fill_record_fields_config17.json"}, - {"fill_record_fields_config18.json"} + {"fill_record_fields_config18.json"}, + {"fill_record_fields_config19.json"}, + {"fill_record_fields_config20.json"}, + {"fill_record_fields_config21.json"}, + {"fill_record_fields_config22.json"}, + {"fill_record_fields_config23.json"} }; } } diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config19.json b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config19.json new file mode 100644 index 000000000000..33bb1d5aa158 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config19.json @@ -0,0 +1,30 @@ +{ + "position": { + "line": 16, + "character": 27 + }, + "source": "fill_record_fields_source16.bal", + "description": "Fill record fields in object field", + "expected": [ + { + "title": "Fill 'Foo' required fields", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 16, + "character": 27 + }, + "end": { + "line": 16, + "character": 27 + } + }, + "newText": ",id: 0" + } + ], + "resolvable": false + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config20.json b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config20.json new file mode 100644 index 000000000000..7cc091c592b1 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config20.json @@ -0,0 +1,30 @@ +{ + "position": { + "line": 18, + "character": 27 + }, + "source": "fill_record_fields_source16.bal", + "description": "Fill record fields in object field", + "expected": [ + { + "title": "Fill 'Bar' required fields", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 18, + "character": 27 + }, + "end": { + "line": 18, + "character": 27 + } + }, + "newText": ",id: 0" + } + ], + "resolvable": false + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config21.json b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config21.json new file mode 100644 index 000000000000..fa7b5540e5e9 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config21.json @@ -0,0 +1,30 @@ +{ + "position": { + "line": 20, + "character": 27 + }, + "source": "fill_record_fields_source16.bal", + "description": "Fill record fields in object field", + "expected": [ + { + "title": "Fill 'Baz' required fields", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 20, + "character": 27 + }, + "end": { + "line": 20, + "character": 27 + } + }, + "newText": ",id: 0" + } + ], + "resolvable": false + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config22.json b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config22.json new file mode 100644 index 000000000000..ae13570a40f8 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config22.json @@ -0,0 +1,30 @@ +{ + "position": { + "line": 22, + "character": 46 + }, + "source": "fill_record_fields_source16.bal", + "description": "Fill record fields in object field", + "expected": [ + { + "title": "Fill 'record {|readonly string 'type; readonly int id; anydata & readonly...;|}' required fields", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 22, + "character": 46 + }, + "end": { + "line": 22, + "character": 46 + } + }, + "newText": ",id: 0" + } + ], + "resolvable": false + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config23.json b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config23.json new file mode 100644 index 000000000000..7ec91e60b3c1 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/config/fill_record_fields_config23.json @@ -0,0 +1,30 @@ +{ + "position": { + "line": 27, + "character": 45 + }, + "source": "fill_record_fields_source16.bal", + "description": "Fill record fields in object field", + "expected": [ + { + "title": "Fill 'record {|readonly string 'type; readonly int id; anydata & readonly...;|}' required fields", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 27, + "character": 45 + }, + "end": { + "line": 27, + "character": 45 + } + }, + "newText": ",id: 0" + } + ], + "resolvable": false + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/source/fill_record_fields_source16.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/source/fill_record_fields_source16.bal new file mode 100644 index 000000000000..9832377fd6f3 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/fill-record-fields/source/fill_record_fields_source16.bal @@ -0,0 +1,29 @@ +type Foo record { + string 'type; + int id; +}; + +type Bar readonly & record { + string 'type; + int id; +}; + +type Baz record { + readonly string 'type; + int id; +}; + +function testFillRecordFields() { + Foo foo = {'type: "foo"}; + + Bar bar = {'type: "bar"}; + + Baz baz = {'type: "baz"}; + + Foo & readonly fooReadonly = {'type: "foo"}; + + record { + string 'type; + int id; + } & readonly fooReadonly2 = {'type: "foo"}; +} From cc5e506102da5a69c7bfa3178d82cfa60ab59462 Mon Sep 17 00:00:00 2001 From: LakshanWeerasinghe Date: Wed, 9 Aug 2023 15:15:10 +0530 Subject: [PATCH 4/4] Add tests for fill record field completions --- ...mapping_constructor_expr_ctx_config10.json | 36 +++++++++++++++++++ ...mapping_constructor_expr_ctx_config11.json | 36 +++++++++++++++++++ ...mapping_constructor_expr_ctx_config12.json | 36 +++++++++++++++++++ ...mapping_constructor_expr_ctx_config13.json | 36 +++++++++++++++++++ ...mapping_constructor_expr_ctx_config14.json | 36 +++++++++++++++++++ .../mapping_constructor_expr_ctx_config9.json | 36 +++++++++++++++++++ .../mapping_constructor_expr_ctx_source8.bal | 33 +++++++++++++++++ 7 files changed, 249 insertions(+) create mode 100644 language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config10.json create mode 100644 language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config11.json create mode 100644 language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config12.json create mode 100644 language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config13.json create mode 100644 language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config14.json create mode 100644 language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config9.json create mode 100644 language-server/modules/langserver-core/src/test/resources/completion/expression_context/source/mapping_constructor_expr_ctx_source8.bal diff --git a/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config10.json b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config10.json new file mode 100644 index 000000000000..2c4ea2562919 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config10.json @@ -0,0 +1,36 @@ +{ + "position": { + "line": 20, + "character": 28 + }, + "source": "expression_context/source/mapping_constructor_expr_ctx_source8.bal", + "description": "", + "items": [ + { + "label": "readonly", + "kind": "Keyword", + "detail": "Keyword", + "sortText": "U", + "filterText": "readonly", + "insertText": "readonly ", + "insertTextFormat": "Snippet" + }, + { + "label": "Fill Bar Required Fields", + "kind": "Property", + "detail": "Bar", + "sortText": "R", + "filterText": "fill", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + }, + { + "label": "id", + "kind": "Field", + "detail": "Bar.id", + "sortText": "K", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config11.json b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config11.json new file mode 100644 index 000000000000..8ebbb978ea9a --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config11.json @@ -0,0 +1,36 @@ +{ + "position": { + "line": 22, + "character": 28 + }, + "source": "expression_context/source/mapping_constructor_expr_ctx_source8.bal", + "description": "", + "items": [ + { + "label": "readonly", + "kind": "Keyword", + "detail": "Keyword", + "sortText": "U", + "filterText": "readonly", + "insertText": "readonly ", + "insertTextFormat": "Snippet" + }, + { + "label": "Fill Baz Required Fields", + "kind": "Property", + "detail": "Baz", + "sortText": "R", + "filterText": "fill", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + }, + { + "label": "id", + "kind": "Field", + "detail": "Baz.id", + "sortText": "K", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config12.json b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config12.json new file mode 100644 index 000000000000..42e7a29a2106 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config12.json @@ -0,0 +1,36 @@ +{ + "position": { + "line": 24, + "character": 47 + }, + "source": "expression_context/source/mapping_constructor_expr_ctx_source8.bal", + "description": "", + "items": [ + { + "label": "readonly", + "kind": "Keyword", + "detail": "Keyword", + "sortText": "U", + "filterText": "readonly", + "insertText": "readonly ", + "insertTextFormat": "Snippet" + }, + { + "label": "Fill record {|readonly string 'type; readonly int id; anydata & readonly...;|} Required Fields", + "kind": "Property", + "detail": "record {|readonly string 'type; readonly int id; anydata & readonly...;|}", + "sortText": "R", + "filterText": "fill", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + }, + { + "label": "id", + "kind": "Field", + "detail": "(record {|readonly string 'type; readonly int id; anydata & readonly...;|}).id", + "sortText": "K", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config13.json b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config13.json new file mode 100644 index 000000000000..ab98c109a13f --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config13.json @@ -0,0 +1,36 @@ +{ + "position": { + "line": 29, + "character": 46 + }, + "source": "expression_context/source/mapping_constructor_expr_ctx_source8.bal", + "description": "", + "items": [ + { + "label": "readonly", + "kind": "Keyword", + "detail": "Keyword", + "sortText": "U", + "filterText": "readonly", + "insertText": "readonly ", + "insertTextFormat": "Snippet" + }, + { + "label": "Fill record {|readonly string 'type; readonly int id; anydata & readonly...;|} Required Fields", + "kind": "Property", + "detail": "record {|readonly string 'type; readonly int id; anydata & readonly...;|}", + "sortText": "R", + "filterText": "fill", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + }, + { + "label": "id", + "kind": "Field", + "detail": "(record {|readonly string 'type; readonly int id; anydata & readonly...;|}).id", + "sortText": "K", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config14.json b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config14.json new file mode 100644 index 000000000000..c82c055b1afc --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config14.json @@ -0,0 +1,36 @@ +{ + "position": { + "line": 31, + "character": 24 + }, + "source": "expression_context/source/mapping_constructor_expr_ctx_source8.bal", + "description": "", + "items": [ + { + "label": "readonly", + "kind": "Keyword", + "detail": "Keyword", + "sortText": "U", + "filterText": "readonly", + "insertText": "readonly ", + "insertTextFormat": "Snippet" + }, + { + "label": "Fill A Required Fields", + "kind": "Property", + "detail": "A", + "sortText": "R", + "filterText": "fill", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + }, + { + "label": "id", + "kind": "Field", + "detail": "A.id", + "sortText": "K", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config9.json b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config9.json new file mode 100644 index 000000000000..a4bbb2723f6b --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/mapping_constructor_expr_ctx_config9.json @@ -0,0 +1,36 @@ +{ + "position": { + "line": 18, + "character": 28 + }, + "source": "expression_context/source/mapping_constructor_expr_ctx_source8.bal", + "description": "", + "items": [ + { + "label": "readonly", + "kind": "Keyword", + "detail": "Keyword", + "sortText": "U", + "filterText": "readonly", + "insertText": "readonly ", + "insertTextFormat": "Snippet" + }, + { + "label": "Fill Foo Required Fields", + "kind": "Property", + "detail": "Foo", + "sortText": "R", + "filterText": "fill", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + }, + { + "label": "id", + "kind": "Field", + "detail": "Foo.id", + "sortText": "K", + "insertText": "id: ${1:0}", + "insertTextFormat": "Snippet" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/expression_context/source/mapping_constructor_expr_ctx_source8.bal b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/source/mapping_constructor_expr_ctx_source8.bal new file mode 100644 index 000000000000..18ba350a4215 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/source/mapping_constructor_expr_ctx_source8.bal @@ -0,0 +1,33 @@ +type Foo record { + string 'type; + int id; +}; + +type Bar readonly & record { + string 'type; + int id; +}; + +type Baz record { + readonly string 'type; + int id; +}; + +type A Baz; + +function testFillRecordFields() { + Foo foo = {'type: "foo",}; + + Bar bar = {'type: "bar",}; + + Baz baz = {'type: "baz",}; + + Foo & readonly fooReadonly = {'type: "foo",}; + + record { + string 'type; + int id; + } & readonly fooReadonly2 = {'type: "foo",}; + + A a = {'type: "baz",}; +}