From d068d5cef377045649ac129096c7bd7678a731b0 Mon Sep 17 00:00:00 2001 From: volodya-lombrozo Date: Fri, 7 Aug 2026 10:54:50 +0300 Subject: [PATCH 1/4] feat(#1170): Add lint rule for package members without void attributes --- .../design/package-member-without-void.xsl | 35 +++++++++++++++++++ .../allows-nested-void-less-formation.yaml | 13 +++++++ .../allows-package-member-with-void.yaml | 11 ++++++ ...s-void-less-formation-without-package.yaml | 9 +++++ ...ches-atom-package-member-without-void.yaml | 13 +++++++ .../catches-both-top-level-members.yaml | 17 +++++++++ .../catches-only-top-level-member.yaml | 15 ++++++++ .../catches-package-member-without-void.yaml | 13 +++++++ 8 files changed, 126 insertions(+) create mode 100644 src/main/resources/org/eolang/lints/design/package-member-without-void.xsl create mode 100644 src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-nested-void-less-formation.yaml create mode 100644 src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-package-member-with-void.yaml create mode 100644 src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-void-less-formation-without-package.yaml create mode 100644 src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-atom-package-member-without-void.yaml create mode 100644 src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml create mode 100644 src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-only-top-level-member.yaml create mode 100644 src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-package-member-without-void.yaml diff --git a/src/main/resources/org/eolang/lints/design/package-member-without-void.xsl b/src/main/resources/org/eolang/lints/design/package-member-without-void.xsl new file mode 100644 index 000000000..285d44b45 --- /dev/null +++ b/src/main/resources/org/eolang/lints/design/package-member-without-void.xsl @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + warning + The package member + + does not declare any void attributes, so it can never be reached in the implicit (receiver) form, only through the package namespace + + + + + + diff --git a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-nested-void-less-formation.yaml b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-nested-void-less-formation.yaml new file mode 100644 index 000000000..41fe04bcc --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-nested-void-less-formation.yaml @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +sheets: + - /org/eolang/lints/design/package-member-without-void.xsl +defects: 0 +input: | + +package foo + + # Bar. + [x] > bar + # Baz. + [] > baz diff --git a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-package-member-with-void.yaml b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-package-member-with-void.yaml new file mode 100644 index 000000000..31687c72f --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-package-member-with-void.yaml @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +sheets: + - /org/eolang/lints/design/package-member-without-void.xsl +defects: 0 +input: | + +package foo + + # Bar. + [x] > bar diff --git a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-void-less-formation-without-package.yaml b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-void-less-formation-without-package.yaml new file mode 100644 index 000000000..8d9063e43 --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/allows-void-less-formation-without-package.yaml @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +sheets: + - /org/eolang/lints/design/package-member-without-void.xsl +defects: 0 +input: | + # Stdin. + [] > stdin diff --git a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-atom-package-member-without-void.yaml b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-atom-package-member-without-void.yaml new file mode 100644 index 000000000..705cf4554 --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-atom-package-member-without-void.yaml @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +sheets: + - /org/eolang/lints/design/package-member-without-void.xsl +asserts: + - /defects[count(defect[@severity='warning'])=1] + - /defects/defect[@line='4'] +input: | + +package foo + + # Bar. + [] > bar /number diff --git a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml new file mode 100644 index 000000000..26cb7380b --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +sheets: + - /org/eolang/lints/design/package-member-without-void.xsl +asserts: + - /defects[count(defect[@severity='warning'])=2] + - /defects/defect[@line='4'] + - /defects/defect[@line='7'] +input: | + +package foo + + # Bar. + [] > bar + + # Baz. + [] > baz diff --git a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-only-top-level-member.yaml b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-only-top-level-member.yaml new file mode 100644 index 000000000..c71d5cc94 --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-only-top-level-member.yaml @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +sheets: + - /org/eolang/lints/design/package-member-without-void.xsl +asserts: + - /defects[count(defect[@severity='warning'])=1] + - /defects/defect[@line='4'] +input: | + +package foo + + # Bar. + [] > bar + # Baz. + [] > baz diff --git a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-package-member-without-void.yaml b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-package-member-without-void.yaml new file mode 100644 index 000000000..c1d186e5f --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-package-member-without-void.yaml @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +sheets: + - /org/eolang/lints/design/package-member-without-void.xsl +asserts: + - /defects[count(defect[@severity='warning'])=1] + - /defects/defect[@line='4'] +input: | + +package foo + + # Bar. + [] > bar From 131e7a0c17e7339b1101773bdfd4902001929d5b Mon Sep 17 00:00:00 2001 From: volodya-lombrozo Date: Fri, 7 Aug 2026 11:00:09 +0300 Subject: [PATCH 2/4] docs(#1170): Add design motive for package member without void lint --- .../design/package-member-without-void.md | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/main/resources/org/eolang/motives/design/package-member-without-void.md diff --git a/src/main/resources/org/eolang/motives/design/package-member-without-void.md b/src/main/resources/org/eolang/motives/design/package-member-without-void.md new file mode 100644 index 000000000..f88d00b23 --- /dev/null +++ b/src/main/resources/org/eolang/motives/design/package-member-without-void.md @@ -0,0 +1,36 @@ +# Package member without void + +A member of a package is also implicitly a method of any object whose forma +matches the package name: `bytes.as-number x` and `x.as-number` reach the +same `Φ.bytes.as-number` object, because the runtime binds the receiver into +the member's first void attribute when the implicit, dotted form is used. A +member that declares no void attributes has no slot for that receiver, so +the implicit form fails at runtime, even though the explicit, namespaced +form works fine. + +Incorrect: + +```eo ++package bytes + +# As number. +[] > as-number +``` + +Correct: + +```eo ++package bytes + +# As number. +[b] > as-number +``` + +Only top-level objects of a file that declares `+package` are checked: a +void-less formation is fine everywhere else, for example a ready-made +constant such as `[] > stdin`, or a local helper nested inside another +formation's body. + +See [objectionary/lints#1170] for the discussion that motivated this lint. + +[objectionary/lints#1170]: https://github.com/objectionary/lints/issues/1170 From 740f87562d63ee182a5dc14c4cc3f6a0c645793f Mon Sep 17 00:00:00 2001 From: volodya-lombrozo Date: Fri, 7 Aug 2026 12:42:27 +0300 Subject: [PATCH 3/4] test(#1170): Update line numbers in package-member-without-void test assertions --- .../catches-both-top-level-members.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml index 26cb7380b..cd002ce6d 100644 --- a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml +++ b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml @@ -5,13 +5,11 @@ sheets: - /org/eolang/lints/design/package-member-without-void.xsl asserts: - /defects[count(defect[@severity='warning'])=2] - - /defects/defect[@line='4'] - - /defects/defect[@line='7'] + - /defects/defect[@line='3'] + - /defects/defect[@line='5'] input: | +package foo - # Bar. [] > bar - # Baz. [] > baz From ca8fdb4cc7bf912d82fc64bcef1bc36eed0caf3a Mon Sep 17 00:00:00 2001 From: volodya-lombrozo Date: Fri, 7 Aug 2026 13:01:18 +0300 Subject: [PATCH 4/4] docs(#1170): Clarify package member void documentation and update vocabulary --- .../config/vocabularies/Custom/accept.txt | 1 + .../design/package-member-without-void.md | 18 +++++++++--------- .../catches-both-top-level-members.yaml | 15 --------------- 3 files changed, 10 insertions(+), 24 deletions(-) delete mode 100644 src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml diff --git a/.github/styles/config/vocabularies/Custom/accept.txt b/.github/styles/config/vocabularies/Custom/accept.txt index b2ac2fdbc..1885313f9 100644 --- a/.github/styles/config/vocabularies/Custom/accept.txt +++ b/.github/styles/config/vocabularies/Custom/accept.txt @@ -18,3 +18,4 @@ inlined [Ii]nlining [Ss]ubgraph [Aa]pplication +[Ff]orma(e)? diff --git a/src/main/resources/org/eolang/motives/design/package-member-without-void.md b/src/main/resources/org/eolang/motives/design/package-member-without-void.md index f88d00b23..4906cbd81 100644 --- a/src/main/resources/org/eolang/motives/design/package-member-without-void.md +++ b/src/main/resources/org/eolang/motives/design/package-member-without-void.md @@ -1,12 +1,13 @@ # Package member without void A member of a package is also implicitly a method of any object whose forma -matches the package name: `bytes.as-number x` and `x.as-number` reach the +matches the package name. `bytes.as-number x` and `x.as-number` reach the same `Φ.bytes.as-number` object, because the runtime binds the receiver into -the member's first void attribute when the implicit, dotted form is used. A -member that declares no void attributes has no slot for that receiver, so -the implicit form fails at runtime, even though the explicit, namespaced -form works fine. +the member's first void attribute when the implicit, dotted form is used. + +A member that declares no void attributes has no slot for that receiver. +The implicit form fails at runtime then, even though the explicit, +package-qualified form works fine. Incorrect: @@ -26,10 +27,9 @@ Correct: [b] > as-number ``` -Only top-level objects of a file that declares `+package` are checked: a -void-less formation is fine everywhere else, for example a ready-made -constant such as `[] > stdin`, or a local helper nested inside another -formation's body. +Only top-level objects of a file that declares `+package` are checked. A +void-less formation is fine everywhere else: a ready-made constant such as +`[] > stdin`, or a local helper nested inside another formation's body. See [objectionary/lints#1170] for the discussion that motivated this lint. diff --git a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml b/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml deleted file mode 100644 index cd002ce6d..000000000 --- a/src/test/resources/org/eolang/lints/packs/single/package-member-without-void/catches-both-top-level-members.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com -# SPDX-License-Identifier: MIT ---- -sheets: - - /org/eolang/lints/design/package-member-without-void.xsl -asserts: - - /defects[count(defect[@severity='warning'])=2] - - /defects/defect[@line='3'] - - /defects/defect[@line='5'] -input: | - +package foo - - [] > bar - - [] > baz