From c5686b10148a4ff882a1acc6d77367200d25036e Mon Sep 17 00:00:00 2001 From: Philipp Burckhardt Date: Sat, 13 Dec 2025 18:48:16 -0600 Subject: [PATCH 1/6] build: add ESLint rule disallowing string concatenation in error messages --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: passed - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: passed - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: na - task: lint_license_headers status: passed --- --- etc/eslint/rules/stdlib.js | 19 +++ .../@stdlib/_tools/eslint/rules/lib/index.js | 9 ++ .../rules/no-error-string-concat/README.md | 124 +++++++++++++++ .../no-error-string-concat/examples/index.js | 51 ++++++ .../rules/no-error-string-concat/lib/index.js | 39 +++++ .../rules/no-error-string-concat/lib/main.js | 145 ++++++++++++++++++ .../rules/no-error-string-concat/package.json | 53 +++++++ .../test/fixtures/invalid.js | 123 +++++++++++++++ .../test/fixtures/unvalidated.js | 57 +++++++ .../test/fixtures/valid.js | 63 ++++++++ .../rules/no-error-string-concat/test/test.js | 86 +++++++++++ 11 files changed, 769 insertions(+) create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/examples/index.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/lib/index.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/lib/main.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/package.json create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/invalid.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/unvalidated.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/valid.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/test.js diff --git a/etc/eslint/rules/stdlib.js b/etc/eslint/rules/stdlib.js index a55ab53096ef..f8a35c60aba8 100644 --- a/etc/eslint/rules/stdlib.js +++ b/etc/eslint/rules/stdlib.js @@ -4157,6 +4157,25 @@ rules[ 'stdlib/no-dynamic-require' ] = 'error'; */ rules[ 'stdlib/no-empty-comments' ] = 'error'; +/** +* Disallow string concatenation in error messages. +* +* @name no-error-string-concat +* @memberof rules +* @type {string} +* @default 'error' +* +* @example +* // Bad... +* throw new Error( 'invalid argument. Value: `' + value + '`.' ); +* +* @example +* // Good... +* throw new Error( 'unexpected error.' ); +* throw new Error( format( 'invalid argument. Value: `%s`.', value ) ); +*/ +rules[ 'stdlib/no-error-string-concat' ] = 'error'; + /** * Enforce that `require()` expressions are not immediately invoked. * diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js index 817b943efba0..0560718171bd 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js @@ -882,6 +882,15 @@ setReadOnly( rules, 'no-dynamic-require', require( '@stdlib/_tools/eslint/rules/ */ setReadOnly( rules, 'no-empty-comments', require( '@stdlib/_tools/eslint/rules/no-empty-comments' ) ); +/** +* @name no-error-string-concat +* @memberof rules +* @readonly +* @type {Function} +* @see {@link module:@stdlib/_tools/eslint/rules/no-error-string-concat} +*/ +setReadOnly( rules, 'no-error-string-concat', require( '@stdlib/_tools/eslint/rules/no-error-string-concat' ) ); + /** * @name no-immediate-require * @memberof rules diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md new file mode 100644 index 000000000000..35d48d3e9f7c --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md @@ -0,0 +1,124 @@ + + +# no-error-string-concat + +> [ESLint rule][eslint-rules] disallowing string concatenation in error messages. + +
+ +
+ + + +
+ +## Usage + +```javascript +var rule = require( '@stdlib/_tools/eslint/rules/no-error-string-concat' ); +``` + +#### rule + +[ESLint rule][eslint-rules] disallowing string concatenation in error messages. + +**Bad**: + + + + + +```javascript +throw new Error( 'invalid argument. Value: `' + value + '`.' ); +``` + +**Good**: + + + +```javascript +var format = require( '@stdlib/string/format' ); + +throw new Error( format( 'invalid argument. Value: `%s`.', value ) ); +``` + +
+ + + +
+ +## Examples + +```javascript +var Linter = require( 'eslint' ).Linter; +var rule = require( '@stdlib/_tools/eslint/rules/no-error-string-concat' ); + +var linter = new Linter(); +var result; +var code; + +code = 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );'; + +linter.defineRule( 'no-error-string-concat', rule ); + +result = linter.verify( code, { + 'rules': { + 'no-error-string-concat': 'error' + } +}); +/* returns + [ + { + 'ruleId': 'no-error-string-concat', + 'severity': 2, + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'line': 1, + 'column': 18, + 'nodeType': 'BinaryExpression', + 'endLine': 1, + 'endColumn': 61 + } + ] +*/ +``` + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/examples/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/examples/index.js new file mode 100644 index 000000000000..6ee5062685be --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/examples/index.js @@ -0,0 +1,51 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var Linter = require( 'eslint' ).Linter; +var rule = require( './../lib' ); + +var linter = new Linter(); +var result; +var code; + +code = 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );'; + +linter.defineRule( 'no-error-string-concat', rule ); + +result = linter.verify( code, { + 'rules': { + 'no-error-string-concat': 'error' + } +}); +console.log( result ); +/* => + [ + { + 'ruleId': 'no-error-string-concat', + 'severity': 2, + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'line': 1, + 'column': 18, + 'nodeType': 'BinaryExpression', + 'endLine': 1, + 'endColumn': 61 + } + ] +*/ diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/lib/index.js new file mode 100644 index 000000000000..52587016940d --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/lib/index.js @@ -0,0 +1,39 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* ESLint rule disallowing string concatenation in error messages. +* +* @module @stdlib/_tools/eslint/rules/no-error-string-concat +* +* @example +* var rule = require( '@stdlib/_tools/eslint/rules/no-error-string-concat' ); +* +* console.log( rule ); +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/lib/main.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/lib/main.js new file mode 100644 index 000000000000..00e544a04ee4 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/lib/main.js @@ -0,0 +1,145 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// VARIABLES // + +var ERROR_CONSTRUCTORS = [ + 'Error', + 'TypeError', + 'RangeError', + 'SyntaxError', + 'ReferenceError', + 'URIError', + 'EvalError' +]; +var rule; + + +// FUNCTIONS // + +/** +* Checks whether a node is a BinaryExpression using the addition operator. +* +* @private +* @param {ASTNode} node - AST node +* @returns {boolean} boolean indicating whether the node is a binary addition expression +*/ +function isBinaryAddition( node ) { + return node.type === 'BinaryExpression' && node.operator === '+'; +} + +/** +* Checks whether a callee name is an error constructor. +* +* @private +* @param {string} name - callee name +* @returns {boolean} boolean indicating whether the name is an error constructor +*/ +function isErrorConstructor( name ) { + var i; + for ( i = 0; i < ERROR_CONSTRUCTORS.length; i++ ) { + if ( name === ERROR_CONSTRUCTORS[ i ] ) { + return true; + } + } + return false; +} + +/** +* Rule for validating that `@stdlib/string/format` is used instead of string concatenation in error messages. +* +* @param {Object} context - ESLint context +* @returns {Object} validators +*/ +function main( context ) { + /** + * Reports the error message. + * + * @private + * @param {ASTNode} node - node to report + */ + function report( node ) { + context.report({ + 'node': node, + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.' + }); + } + + /** + * Checks whether an error constructor call uses string concatenation in its first argument. + * + * @private + * @param {ASTNode} node - CallExpression or NewExpression node to examine + */ + function validate( node ) { + var firstArg; + var callee; + var name; + + callee = node.callee; + + // Get the constructor name: + if ( callee.type === 'Identifier' ) { + name = callee.name; + } else { + return; + } + + // Check if this is a call to an error constructor: + if ( !isErrorConstructor( name ) ) { + return; + } + + // Check if there is at least one argument: + if ( node.arguments.length === 0 ) { + return; + } + + firstArg = node.arguments[ 0 ]; + + // Check if the first argument uses the addition operator: + if ( isBinaryAddition( firstArg ) ) { + report( firstArg ); + } + } + + return { + 'NewExpression': validate, + 'CallExpression': validate + }; +} + + +// MAIN // + +rule = { + 'meta': { + 'docs': { + 'description': 'disallow string concatenation in error messages' + }, + 'schema': [] + }, + 'create': main +}; + + +// EXPORTS // + +module.exports = rule; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/package.json new file mode 100644 index 000000000000..b012505ef738 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/package.json @@ -0,0 +1,53 @@ +{ + "name": "@stdlib/_tools/eslint/rules/no-error-string-concat", + "version": "0.0.0", + "description": "ESLint rule disallowing string concatenation in error messages.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "bin": {}, + "main": "./lib", + "directories": { + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "keywords": [ + "stdlib", + "tools", + "tool", + "eslint", + "lint", + "custom", + "rules", + "rule", + "plugin", + "error", + "string", + "concatenation", + "format" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/invalid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/invalid.js new file mode 100644 index 000000000000..7d8b7fffbf1c --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/invalid.js @@ -0,0 +1,123 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var invalid = []; +var test; + +// Simple string concatenation in Error: +test = { + 'code': 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );', + 'errors': [ + { + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'type': 'BinaryExpression' + } + ] +}; +invalid.push( test ); + +// String concatenation in TypeError: +test = { + 'code': 'throw new TypeError( \'expected a string. Value: `\' + x + \'`.\' );', + 'errors': [ + { + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'type': 'BinaryExpression' + } + ] +}; +invalid.push( test ); + +// String concatenation in RangeError: +test = { + 'code': 'throw new RangeError( idx + \' is out of bounds.\' );', + 'errors': [ + { + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'type': 'BinaryExpression' + } + ] +}; +invalid.push( test ); + +// Error called without new: +test = { + 'code': 'throw Error( \'invalid argument. Value: `\' + value + \'`.\' );', + 'errors': [ + { + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'type': 'BinaryExpression' + } + ] +}; +invalid.push( test ); + +// String concatenation in SyntaxError: +test = { + 'code': 'throw new SyntaxError( \'unexpected token: \' + token );', + 'errors': [ + { + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'type': 'BinaryExpression' + } + ] +}; +invalid.push( test ); + +// String concatenation in ReferenceError: +test = { + 'code': 'throw new ReferenceError( name + \' is not defined.\' );', + 'errors': [ + { + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'type': 'BinaryExpression' + } + ] +}; +invalid.push( test ); + +// String concatenation in URIError: +test = { + 'code': 'throw new URIError( \'invalid URI: \' + uri );', + 'errors': [ + { + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'type': 'BinaryExpression' + } + ] +}; +invalid.push( test ); + +// String concatenation in EvalError: +test = { + 'code': 'throw new EvalError( \'eval error: \' + msg );', + 'errors': [ + { + 'message': 'Use `@stdlib/string/format` instead of string concatenation in error messages.', + 'type': 'BinaryExpression' + } + ] +}; +invalid.push( test ); + + +// EXPORTS // + +module.exports = invalid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/unvalidated.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/unvalidated.js new file mode 100644 index 000000000000..0b91a6c72d43 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/unvalidated.js @@ -0,0 +1,57 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var valid = []; +var test; + +// String concatenation in non-error constructor: +test = { + 'code': 'new MyClass( \'prefix\' + value );' +}; +valid.push( test ); + +// String concatenation in regular function call: +test = { + 'code': 'console.log( \'value: \' + x );' +}; +valid.push( test ); + +// String concatenation assigned to variable, then used in error: +test = { + 'code': 'var msg = \'invalid: \' + x;\nthrow new Error( msg );' +}; +valid.push( test ); + +// Member expression (not a simple identifier): +test = { + 'code': 'throw new errors.CustomError( \'prefix\' + value );' +}; +valid.push( test ); + +// String concatenation in second argument: +test = { + 'code': 'throw new Error( \'message\', \'cause: \' + x );' +}; +valid.push( test ); + + +// EXPORTS // + +module.exports = valid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/valid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/valid.js new file mode 100644 index 000000000000..e06d456d3a56 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/valid.js @@ -0,0 +1,63 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var valid = []; +var test; + +// Using a string literal: +test = { + 'code': 'throw new Error( \'unexpected error.\' );' +}; +valid.push( test ); + +// Using format function: +test = { + 'code': 'throw new Error( format( \'invalid argument. First argument must be a number. Value: `%s`.\', value ) );' +}; +valid.push( test ); + +// Using a variable: +test = { + 'code': 'var msg = \'error message\';\nthrow new Error( msg );' +}; +valid.push( test ); + +// Error constructor without arguments: +test = { + 'code': 'throw new Error();' +}; +valid.push( test ); + +// TypeError with string literal: +test = { + 'code': 'throw new TypeError( \'expected a string.\' );' +}; +valid.push( test ); + +// RangeError with format: +test = { + 'code': 'throw new RangeError( format( \'index out of bounds. Value: `%d`.\', idx ) );' +}; +valid.push( test ); + + +// EXPORTS // + +module.exports = valid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/test.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/test.js new file mode 100644 index 000000000000..c204a6820904 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/test.js @@ -0,0 +1,86 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var RuleTester = require( 'eslint' ).RuleTester; +var rule = require( './../lib' ); + + +// FIXTURES // + +var valid = require( './fixtures/valid.js' ); +var invalid = require( './fixtures/invalid.js' ); +var unvalidated = require( './fixtures/unvalidated.js' ); + + +// TESTS // + +tape( 'main export is an object', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof rule, 'object', 'main export is an object' ); + t.end(); +}); + +tape( 'the rule positively validates code using `format` instead of string concatenation in error messages', function test( t ) { + var tester = new RuleTester(); + + try { + tester.run( 'no-error-string-concat', rule, { + 'valid': valid, + 'invalid': [] + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +}); + +tape( 'the rule negatively validates code using string concatenation instead of `format` in error messages', function test( t ) { + var tester = new RuleTester(); + + try { + tester.run( 'no-error-string-concat', rule, { + 'valid': [], + 'invalid': invalid + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +}); + +tape( 'the rule does not validate string concatenation outside of error constructors', function test( t ) { + var tester = new RuleTester(); + + try { + tester.run( 'no-error-string-concat', rule, { + 'valid': unvalidated, + 'invalid': [] + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +}); From 7fa9bda6a798274c37970427270ed7c7d32acc4e Mon Sep 17 00:00:00 2001 From: Athan Date: Mon, 15 Dec 2025 18:37:31 -0800 Subject: [PATCH 2/6] docs: update example Signed-off-by: Athan --- .../_tools/eslint/rules/no-error-string-concat/README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md index 35d48d3e9f7c..e9c9d077110e 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md @@ -73,14 +73,11 @@ var Linter = require( 'eslint' ).Linter; var rule = require( '@stdlib/_tools/eslint/rules/no-error-string-concat' ); var linter = new Linter(); -var result; -var code; - -code = 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );'; +var code = 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );'; linter.defineRule( 'no-error-string-concat', rule ); -result = linter.verify( code, { +var result = linter.verify( code, { 'rules': { 'no-error-string-concat': 'error' } From d67c64f0798c8fa2cd607368f532a0d2f9a24cac Mon Sep 17 00:00:00 2001 From: Athan Date: Mon, 15 Dec 2025 18:38:12 -0800 Subject: [PATCH 3/6] docs: update example Signed-off-by: Athan --- .../_tools/eslint/rules/no-error-string-concat/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md index e9c9d077110e..fcf8555bb5ec 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/README.md @@ -73,10 +73,9 @@ var Linter = require( 'eslint' ).Linter; var rule = require( '@stdlib/_tools/eslint/rules/no-error-string-concat' ); var linter = new Linter(); -var code = 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );'; - linter.defineRule( 'no-error-string-concat', rule ); +var code = 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );'; var result = linter.verify( code, { 'rules': { 'no-error-string-concat': 'error' From 86417354e75e5f9f550e58ff3ddc733b5c119825 Mon Sep 17 00:00:00 2001 From: Athan Date: Mon, 15 Dec 2025 18:38:59 -0800 Subject: [PATCH 4/6] docs: update example Signed-off-by: Athan --- .../eslint/rules/no-error-string-concat/examples/index.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/examples/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/examples/index.js index 6ee5062685be..e82f7a5c13c4 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/examples/index.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/examples/index.js @@ -22,14 +22,10 @@ var Linter = require( 'eslint' ).Linter; var rule = require( './../lib' ); var linter = new Linter(); -var result; -var code; - -code = 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );'; - linter.defineRule( 'no-error-string-concat', rule ); -result = linter.verify( code, { +var code = 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );'; +var result = linter.verify( code, { 'rules': { 'no-error-string-concat': 'error' } From f94280c73e93d4144b0508c2124bbfce2237a76b Mon Sep 17 00:00:00 2001 From: Athan Date: Mon, 15 Dec 2025 18:41:39 -0800 Subject: [PATCH 5/6] test: move declaration Signed-off-by: Athan --- .../rules/no-error-string-concat/test/fixtures/invalid.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/invalid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/invalid.js index 7d8b7fffbf1c..dde04596f9b2 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/invalid.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/invalid.js @@ -19,10 +19,9 @@ 'use strict'; var invalid = []; -var test; // Simple string concatenation in Error: -test = { +var test = { 'code': 'throw new Error( \'invalid argument. Value: `\' + value + \'`.\' );', 'errors': [ { From 6eeccc9b2230b656f11cb35c55bee895b8f60b26 Mon Sep 17 00:00:00 2001 From: Athan Date: Mon, 15 Dec 2025 18:42:37 -0800 Subject: [PATCH 6/6] Apply suggestions from code review Signed-off-by: Athan --- .../rules/no-error-string-concat/test/fixtures/unvalidated.js | 3 +-- .../eslint/rules/no-error-string-concat/test/fixtures/valid.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/unvalidated.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/unvalidated.js index 0b91a6c72d43..739356344ba9 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/unvalidated.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/unvalidated.js @@ -19,10 +19,9 @@ 'use strict'; var valid = []; -var test; // String concatenation in non-error constructor: -test = { +var test = { 'code': 'new MyClass( \'prefix\' + value );' }; valid.push( test ); diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/valid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/valid.js index e06d456d3a56..79aaefed8125 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/valid.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/no-error-string-concat/test/fixtures/valid.js @@ -19,10 +19,9 @@ 'use strict'; var valid = []; -var test; // Using a string literal: -test = { +var test = { 'code': 'throw new Error( \'unexpected error.\' );' }; valid.push( test );