From 1836575f457fed8dda7110be023de9977b016a72 Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Fri, 25 Apr 2025 17:09:09 +0300 Subject: [PATCH 01/10] Add noAssignRef rule --- README.md | 1 + package-lock.json | 4 +- src/index.ts | 2 + src/rules/__tests__/no-assign-ref.test.ts | 48 +++++++++++++++++++++++ src/rules/no-assign-ref.ts | 42 ++++++++++++++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/rules/__tests__/no-assign-ref.test.ts create mode 100644 src/rules/no-assign-ref.ts diff --git a/README.md b/README.md index 67c9933..2a1dd32 100644 --- a/README.md +++ b/README.md @@ -44,3 +44,4 @@ export default defineConfig([ | ---------------------- | ------------------------------------- | -------- | | `php/eqeqeq` | Require the use of `===` and `!==` | ❌ | | `php/no-array-keyword` | Disallow the use of the array keyword | ✅ | +| `php/no-assign-ref` | Disallow assigning by reference | ✅ | diff --git a/package-lock.json b/package-lock.json index 4822918..635f347 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "eslint-plugin-php", - "version": "0.0.0", + "version": "0.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "eslint-plugin-php", - "version": "0.0.0", + "version": "0.0.2", "license": "MIT", "dependencies": { "@eslint/core": "^0.13.0", diff --git a/src/index.ts b/src/index.ts index 027e048..df2a048 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ import { PHPLanguage } from './language/php-language'; import { eqeqeq } from './rules/eqeqeq'; import { noArrayKeyword } from './rules/no-array-keyword'; +import { noAssignRef } from './rules/no-assign-ref'; const plugin = { meta: { @@ -15,6 +16,7 @@ const plugin = { rules: { eqeqeq, 'no-array-keyword': noArrayKeyword, + 'no-assign-ref': noAssignRef }, } satisfies ESLint.Plugin; diff --git a/src/rules/__tests__/no-assign-ref.test.ts b/src/rules/__tests__/no-assign-ref.test.ts new file mode 100644 index 0000000..60d19f1 --- /dev/null +++ b/src/rules/__tests__/no-assign-ref.test.ts @@ -0,0 +1,48 @@ +import { RuleTester, type Rule } from 'eslint'; +import php from '../../index'; +import { noAssignRef } from '../no-assign-ref'; + +const ruleTester = new RuleTester({ + plugins: { + php, + }, + language: 'php/php', +}); + +// TODO: Fix the types. +ruleTester.run( + 'no-assign-ref', + noAssignRef as unknown as Rule.RuleModule, + { + valid: ['({ + meta: { + type: 'layout', + fixable: 'code', + docs: { + description: 'Disallow assigning by reference', + }, + messages: { + noAssignRef: + "Assigning by reference is not allowed.", + }, + schema: [], + }, + + create(context) { + return { + "assignref"(_node) { + // TODO: Fix the types. + const node = _node as Bin; + + context.report({ + node, + messageId: 'noAssignRef', + fix(fixer) { + const nodeText = context.sourceCode.getText(node); + + return fixer.replaceText( + node, + nodeText.replace(/&/g, ''), + ); + }, + }); + }, + }; + }, +}); From 1f0b95701639c5408bac5be770df380681c728bd Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Fri, 25 Apr 2025 17:11:09 +0300 Subject: [PATCH 02/10] fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a1dd32..5a4c27b 100644 --- a/README.md +++ b/README.md @@ -44,4 +44,4 @@ export default defineConfig([ | ---------------------- | ------------------------------------- | -------- | | `php/eqeqeq` | Require the use of `===` and `!==` | ❌ | | `php/no-array-keyword` | Disallow the use of the array keyword | ✅ | -| `php/no-assign-ref` | Disallow assigning by reference | ✅ | +| `php/no-assign-ref` | Disallow assigning by reference | ✅ | From 91e70d1536f38cc451bc8c3d0a2296b3f7a7f152 Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Fri, 25 Apr 2025 17:46:53 +0300 Subject: [PATCH 03/10] update type --- src/rules/no-assign-ref.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules/no-assign-ref.ts b/src/rules/no-assign-ref.ts index 577ba78..8fd5be3 100644 --- a/src/rules/no-assign-ref.ts +++ b/src/rules/no-assign-ref.ts @@ -6,7 +6,7 @@ type Options = []; export const noAssignRef = createRule({ meta: { - type: 'layout', + type: 'suggestion', fixable: 'code', docs: { description: 'Disallow assigning by reference', From 896c6592866098ec97d208f5152e93c49c2dbb32 Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Fri, 25 Apr 2025 18:19:44 +0300 Subject: [PATCH 04/10] removed redundant type --- src/rules/no-assign-ref.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/rules/no-assign-ref.ts b/src/rules/no-assign-ref.ts index 8fd5be3..b12ce0a 100644 --- a/src/rules/no-assign-ref.ts +++ b/src/rules/no-assign-ref.ts @@ -1,4 +1,3 @@ -import type { Bin } from 'php-parser'; import { createRule } from '../utils/create-rule'; type MessageIds = 'noAssignRef'; @@ -20,10 +19,7 @@ export const noAssignRef = createRule({ create(context) { return { - "assignref"(_node) { - // TODO: Fix the types. - const node = _node as Bin; - + "assignref"(node) { context.report({ node, messageId: 'noAssignRef', From 2297fa83bd25dd39919946b09ca7a3438bc19705 Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Sun, 27 Apr 2025 20:36:55 +0300 Subject: [PATCH 05/10] format --- src/index.ts | 2 +- src/rules/__tests__/no-assign-ref.test.ts | 67 +++++++++++------------ src/rules/no-assign-ref.ts | 57 ++++++++++--------- 3 files changed, 60 insertions(+), 66 deletions(-) diff --git a/src/index.ts b/src/index.ts index df2a048..473eccb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,7 +16,7 @@ const plugin = { rules: { eqeqeq, 'no-array-keyword': noArrayKeyword, - 'no-assign-ref': noAssignRef + 'no-assign-ref': noAssignRef, }, } satisfies ESLint.Plugin; diff --git a/src/rules/__tests__/no-assign-ref.test.ts b/src/rules/__tests__/no-assign-ref.test.ts index 60d19f1..055c432 100644 --- a/src/rules/__tests__/no-assign-ref.test.ts +++ b/src/rules/__tests__/no-assign-ref.test.ts @@ -10,39 +10,34 @@ const ruleTester = new RuleTester({ }); // TODO: Fix the types. -ruleTester.run( - 'no-assign-ref', - noAssignRef as unknown as Rule.RuleModule, - { - valid: ['({ - meta: { - type: 'suggestion', - fixable: 'code', - docs: { - description: 'Disallow assigning by reference', - }, - messages: { - noAssignRef: - "Assigning by reference is not allowed.", - }, - schema: [], - }, + meta: { + type: 'suggestion', + fixable: 'code', + docs: { + description: 'Disallow assigning by reference', + }, + messages: { + noAssignRef: 'Assigning by reference is not allowed.', + }, + schema: [], + }, - create(context) { - return { - "assignref"(node) { - context.report({ - node, - messageId: 'noAssignRef', - fix(fixer) { - const nodeText = context.sourceCode.getText(node); + create(context) { + return { + assignref(node) { + context.report({ + node, + messageId: 'noAssignRef', + fix(fixer) { + const nodeText = context.sourceCode.getText(node); - return fixer.replaceText( - node, - nodeText.replace(/&/g, ''), - ); - }, - }); - }, - }; - }, + return fixer.replaceText( + node, + nodeText.replace(/&/g, ''), + ); + }, + }); + }, + }; + }, }); From ad4012881116a2035487219d3737745b94731670 Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Sun, 27 Apr 2025 21:29:20 +0300 Subject: [PATCH 06/10] added missing cases --- README.md | 12 +-- src/index.ts | 4 +- src/rules/__tests__/no-assign-ref.test.ts | 118 ++++++++++++++++------ src/rules/disallow-references.ts | 46 +++++++++ src/rules/no-assign-ref.ts | 37 ------- 5 files changed, 140 insertions(+), 77 deletions(-) create mode 100644 src/rules/disallow-references.ts delete mode 100644 src/rules/no-assign-ref.ts diff --git a/README.md b/README.md index b0167fe..9166b9a 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,9 @@ export default defineConfig([ 💡 - Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). -| Rule ID | Description | 🔧 | 💡 | -| ------------------------ | --------------------------------------------------- | --- | --- | -| `php/eqeqeq` | Require the use of `===` and `!==` | | | -| `php/no-array-keyword` | Disallow the use of the array keyword | 🔧 | | -| `php/require-visibility` | Require visibility for class methods and properties | | 💡 | -| `php/no-assign-ref` | Disallow assigning by reference | | 💡 | +| Rule ID | Description | 🔧 | 💡 | +| ------------------------- | --------------------------------------------------- | --- | --- | +| `php/eqeqeq` | Require the use of `===` and `!==` | | | +| `php/no-array-keyword` | Disallow the use of the array keyword | 🔧 | | +| `php/require-visibility` | Require visibility for class methods and properties | | 💡 | +| `php/disallow-references` | Disallow assigning by reference | | 💡 | diff --git a/src/index.ts b/src/index.ts index 1f50656..9dab8a8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import { PHPLanguage } from './language/php-language'; import { eqeqeq } from './rules/eqeqeq'; import { noArrayKeyword } from './rules/no-array-keyword'; -import { noAssignRef } from './rules/no-assign-ref'; +import { disallowReferences } from './rules/disallow-references'; import { requireVisibility } from './rules/require-visibility'; const plugin = { @@ -15,9 +15,9 @@ const plugin = { php: new PHPLanguage(), }, rules: { + 'disallow-references': disallowReferences, eqeqeq, 'no-array-keyword': noArrayKeyword, - 'no-assign-ref': noAssignRef, 'require-visibility': requireVisibility, }, } satisfies ESLint.Plugin; diff --git a/src/rules/__tests__/no-assign-ref.test.ts b/src/rules/__tests__/no-assign-ref.test.ts index 055c432..68bcf13 100644 --- a/src/rules/__tests__/no-assign-ref.test.ts +++ b/src/rules/__tests__/no-assign-ref.test.ts @@ -1,6 +1,6 @@ import { RuleTester, type Rule } from 'eslint'; import php from '../../index'; -import { noAssignRef } from '../no-assign-ref'; +import { disallowReferences } from '../disallow-references'; const ruleTester = new RuleTester({ plugins: { @@ -10,34 +10,88 @@ const ruleTester = new RuleTester({ }); // TODO: Fix the types. -ruleTester.run('no-assign-ref', noAssignRef as unknown as Rule.RuleModule, { - valid: ['({ + meta: { + type: 'layout', + fixable: 'code', + hasSuggestions: true, + docs: { + description: 'Disallow assigning by reference', + }, + messages: { + noAssignRef: 'Assigning by reference is not allowed.', + }, + schema: [], + }, + + create(context) { + return { + 'assignref, parameter[byref="true"], function[byref="true"], variable[byref="true"]'( + node, + ) { + context.report({ + node, + messageId: 'noAssignRef', + suggest: [ + { + desc: 'Remove reference assignment', + fix(fixer) { + const nodeText = + context.sourceCode.getText(node); + + return fixer.replaceText( + node, + nodeText.replace(/&/g, ''), + ); + }, + }, + ], + }); + }, + }; + }, +}); diff --git a/src/rules/no-assign-ref.ts b/src/rules/no-assign-ref.ts deleted file mode 100644 index 1d59c49..0000000 --- a/src/rules/no-assign-ref.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { createRule } from '../utils/create-rule'; - -type MessageIds = 'noAssignRef'; -type Options = []; - -export const noAssignRef = createRule({ - meta: { - type: 'suggestion', - fixable: 'code', - docs: { - description: 'Disallow assigning by reference', - }, - messages: { - noAssignRef: 'Assigning by reference is not allowed.', - }, - schema: [], - }, - - create(context) { - return { - assignref(node) { - context.report({ - node, - messageId: 'noAssignRef', - fix(fixer) { - const nodeText = context.sourceCode.getText(node); - - return fixer.replaceText( - node, - nodeText.replace(/&/g, ''), - ); - }, - }); - }, - }; - }, -}); From ade3a6d7228c1f466e5c5513a12dda6cc1e192c3 Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Sun, 27 Apr 2025 21:36:44 +0300 Subject: [PATCH 07/10] fix lint --- src/rules/__tests__/no-assign-ref.test.ts | 8 ++++---- src/rules/disallow-references.ts | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/rules/__tests__/no-assign-ref.test.ts b/src/rules/__tests__/no-assign-ref.test.ts index 68bcf13..3eb6455 100644 --- a/src/rules/__tests__/no-assign-ref.test.ts +++ b/src/rules/__tests__/no-assign-ref.test.ts @@ -31,7 +31,7 @@ ruleTester.run( endColumn: 37, suggestions: [ { - desc: 'Remove reference assignment', + desc: 'Remove the reference operator (&).', output: '({ @@ -13,6 +13,8 @@ export const disallowReferences = createRule({ }, messages: { noAssignRef: 'Assigning by reference is not allowed.', + noAssignRefFix: 'Remove the reference operator (&).', + }, schema: [], }, @@ -27,7 +29,7 @@ export const disallowReferences = createRule({ messageId: 'noAssignRef', suggest: [ { - desc: 'Remove reference assignment', + messageId: 'noAssignRefFix', fix(fixer) { const nodeText = context.sourceCode.getText(node); From cf461a6fc88b6747bf3898d77b2f243425a88c25 Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Sun, 27 Apr 2025 21:37:37 +0300 Subject: [PATCH 08/10] fix test name --- .../{no-assign-ref.test.ts => disallow-references.test.ts} | 0 src/rules/disallow-references.ts | 1 - 2 files changed, 1 deletion(-) rename src/rules/__tests__/{no-assign-ref.test.ts => disallow-references.test.ts} (100%) diff --git a/src/rules/__tests__/no-assign-ref.test.ts b/src/rules/__tests__/disallow-references.test.ts similarity index 100% rename from src/rules/__tests__/no-assign-ref.test.ts rename to src/rules/__tests__/disallow-references.test.ts diff --git a/src/rules/disallow-references.ts b/src/rules/disallow-references.ts index 7d9addd..385b123 100644 --- a/src/rules/disallow-references.ts +++ b/src/rules/disallow-references.ts @@ -14,7 +14,6 @@ export const disallowReferences = createRule({ messages: { noAssignRef: 'Assigning by reference is not allowed.', noAssignRefFix: 'Remove the reference operator (&).', - }, schema: [], }, From 8e96427090fb33c826a6caa651424ba842b1b8fb Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Sun, 27 Apr 2025 21:38:46 +0300 Subject: [PATCH 09/10] add changeset --- .changeset/few-ducks-mate.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/few-ducks-mate.md diff --git a/.changeset/few-ducks-mate.md b/.changeset/few-ducks-mate.md new file mode 100644 index 0000000..abd2dcd --- /dev/null +++ b/.changeset/few-ducks-mate.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-php': minor +--- + +Add `disallow-references` rule From f4d8768ba24e96374f34dc17b9c2f94e658035db Mon Sep 17 00:00:00 2001 From: Ishay Maya Date: Mon, 28 Apr 2025 18:52:27 +0300 Subject: [PATCH 10/10] update selectors and texts --- README.md | 2 +- src/index.ts | 2 +- .../__tests__/disallow-references.test.ts | 50 +++++++++---------- src/rules/disallow-references.ts | 40 +++++++++------ 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 9166b9a..58b3eee 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ export default defineConfig([ | Rule ID | Description | 🔧 | 💡 | | ------------------------- | --------------------------------------------------- | --- | --- | +| `php/disallow-references` | Disallow the use of references | | 💡 | | `php/eqeqeq` | Require the use of `===` and `!==` | | | | `php/no-array-keyword` | Disallow the use of the array keyword | 🔧 | | | `php/require-visibility` | Require visibility for class methods and properties | | 💡 | -| `php/disallow-references` | Disallow assigning by reference | | 💡 | diff --git a/src/index.ts b/src/index.ts index 9dab8a8..0033488 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,9 @@ import { ESLint } from 'eslint'; import { PHPLanguage } from './language/php-language'; +import { disallowReferences } from './rules/disallow-references'; import { eqeqeq } from './rules/eqeqeq'; import { noArrayKeyword } from './rules/no-array-keyword'; -import { disallowReferences } from './rules/disallow-references'; import { requireVisibility } from './rules/require-visibility'; const plugin = { diff --git a/src/rules/__tests__/disallow-references.test.ts b/src/rules/__tests__/disallow-references.test.ts index 3eb6455..e225889 100644 --- a/src/rules/__tests__/disallow-references.test.ts +++ b/src/rules/__tests__/disallow-references.test.ts @@ -15,23 +15,23 @@ ruleTester.run( disallowReferences as unknown as Rule.RuleModule, { valid: [ - '({ meta: { - type: 'layout', + type: 'suggestion', fixable: 'code', hasSuggestions: true, docs: { - description: 'Disallow assigning by reference', + description: 'Disallow the use of references', }, messages: { - noAssignRef: 'Assigning by reference is not allowed.', - noAssignRefFix: 'Remove the reference operator (&).', + disallowReferences: 'Do not use references (&).', + removeAmp: 'Remove the reference operator (&).', }, schema: [], }, create(context) { return { - 'assignref, parameter[byref="true"], function[byref="true"], variable[byref="true"]'( + 'assignref > .right, parameter[byref="true"], function[byref="true"] > .name, variable[byref="true"]'( node, ) { + const ampKeyWord = context.sourceCode.findClosestKeyword( + node, + '&', + ); + + if (!ampKeyWord) { + return; + } + context.report({ node, - messageId: 'noAssignRef', + loc: { + start: ampKeyWord.start, + end: context.sourceCode.getLoc(node).end, + }, + messageId: 'disallowReferences', suggest: [ { - messageId: 'noAssignRefFix', + messageId: 'removeAmp', fix(fixer) { - const nodeText = - context.sourceCode.getText(node); - - return fixer.replaceText( - node, - nodeText.replace(/&/g, ''), - ); + return fixer.removeRange([ + ampKeyWord.start.offset, + ampKeyWord.end.offset, + ]); }, }, ],