@blumintinc/eslint-plugin-blumint 1.19.5 → 1.19.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -222,7 +222,7 @@ function noFrontendImportsFromFunctionsPatterns(pattern) {
222
222
  module.exports = {
223
223
  meta: {
224
224
  name: '@blumintinc/eslint-plugin-blumint',
225
- version: '1.19.5',
225
+ version: '1.19.6',
226
226
  },
227
227
  parseOptions: {
228
228
  ecmaVersion: 2020,
@@ -77,8 +77,45 @@ exports.noRedundantThisParams = (0, createRule_1.createRule)({
77
77
  }
78
78
  return [];
79
79
  }
80
+ function isExportedClass(node) {
81
+ const parent = node.parent;
82
+ if (!parent) {
83
+ return false;
84
+ }
85
+ if (parent.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration ||
86
+ parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) {
87
+ return true;
88
+ }
89
+ // `export const Foo = class { ... }` exposes the class expression to other
90
+ // files just as an exported declaration does.
91
+ if (node.type === utils_1.AST_NODE_TYPES.ClassExpression &&
92
+ parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator) {
93
+ const declaration = parent.parent;
94
+ const exportNode = declaration?.parent;
95
+ return (exportNode?.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration ||
96
+ exportNode?.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration);
97
+ }
98
+ return false;
99
+ }
80
100
  function collectClassInfo(node) {
81
101
  const methods = new Map();
102
+ // A method's `this.method(...)` call sites are confined to this file only
103
+ // when the class cannot be extended from another file. An `abstract` class
104
+ // exists to be subclassed, and an exported class can be subclassed
105
+ // anywhere; either way subclasses may call an inherited non-private method
106
+ // with a different `this.<member>`, so those methods are externally
107
+ // reachable and must not be reported. See issue #1309.
108
+ const classIsExtensible = Boolean(node.abstract) ||
109
+ isExportedClass(node);
110
+ function computeExternallyReachable(methodName, accessibility) {
111
+ if (!classIsExtensible) {
112
+ return false;
113
+ }
114
+ // `private` (TS) and `#name` (ECMAScript) methods are never inherited,
115
+ // so all of their call sites live in the declaring class body.
116
+ const isPrivate = accessibility === 'private' || methodName.startsWith('#');
117
+ return !isPrivate;
118
+ }
82
119
  function setMethod(methodName, meta) {
83
120
  /**
84
121
  * Prefer instance methods over static methods when names collide.
@@ -120,6 +157,7 @@ exports.noRedundantThisParams = (0, createRule_1.createRule)({
120
157
  params: getMethodParams(member),
121
158
  isStatic: Boolean(member.static),
122
159
  isAbstract: member.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition,
160
+ externallyReachable: computeExternallyReachable(methodName, member.accessibility),
123
161
  });
124
162
  }
125
163
  else if (member.type === utils_1.AST_NODE_TYPES.PropertyDefinition) {
@@ -137,6 +175,7 @@ exports.noRedundantThisParams = (0, createRule_1.createRule)({
137
175
  params,
138
176
  isStatic: false,
139
177
  isAbstract: false,
178
+ externallyReachable: computeExternallyReachable(methodName, member.accessibility),
140
179
  });
141
180
  }
142
181
  }
@@ -432,6 +471,12 @@ exports.noRedundantThisParams = (0, createRule_1.createRule)({
432
471
  for (const [, propStats] of argProperties) {
433
472
  if (propStats.callsWithProperty === methodStats.totalCalls) {
434
473
  for (const violation of propStats.violations) {
474
+ // Skip methods whose call sites are not provably confined to
475
+ // this file: a subclass elsewhere may thread a different
476
+ // `this.<member>` through the same parameter (issue #1309).
477
+ if (violation.methodMeta.externallyReachable) {
478
+ continue;
479
+ }
435
480
  reportAccess(methodName, violation.methodMeta, argIndex, violation.access);
436
481
  }
437
482
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blumintinc/eslint-plugin-blumint",
3
- "version": "1.19.5",
3
+ "version": "1.19.6",
4
4
  "description": "Custom eslint rules for use within BluMint",
5
5
  "author": {
6
6
  "name": "Brodie McGuire",
@@ -1,4 +1,18 @@
1
1
  [
2
+ {
3
+ "version": "1.19.6",
4
+ "date": "2026-07-16T01:27:07.130Z",
5
+ "rules": [
6
+ {
7
+ "name": "no-redundant-this-params",
8
+ "changeType": "fix",
9
+ "issues": [
10
+ 1309
11
+ ],
12
+ "summary": "skip externally-reachable methods (closes #1309)"
13
+ }
14
+ ]
15
+ },
2
16
  {
3
17
  "version": "1.19.5",
4
18
  "date": "2026-07-15T15:24:16.132Z",