From 20b7235cff73956af4eccef4773559d67a52474b Mon Sep 17 00:00:00 2001 From: Philipp Burckhardt Date: Fri, 5 Dec 2025 23:42:56 -0600 Subject: [PATCH 1/4] feat: add `doctest-annotation-spacing` ESLint rule This rule enforces spacing in return annotations in single-line comments (`// returns` and `// =>`). It validates: - Exactly 1 space between `//` and the annotation keyword - Configurable spacing after the keyword (default: 1 space) --- 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 --- --- .../doctest-annotation-spacing/README.md | 182 ++++++++++++++ .../examples/index.js | 57 +++++ .../lib/defaults.json | 3 + .../doctest-annotation-spacing/lib/index.js | 39 +++ .../doctest-annotation-spacing/lib/main.js | 194 +++++++++++++++ .../doctest-annotation-spacing/package.json | 66 +++++ .../test/fixtures/invalid.js | 233 ++++++++++++++++++ .../test/fixtures/valid.js | 124 ++++++++++ .../doctest-annotation-spacing/test/test.js | 121 +++++++++ 9 files changed, 1019 insertions(+) create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/examples/index.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/defaults.json create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/index.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/main.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/package.json create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/fixtures/invalid.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/fixtures/valid.js create mode 100644 lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/test.js diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md new file mode 100644 index 000000000000..bc54c87290e4 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md @@ -0,0 +1,182 @@ + + +# doctest-annotation-spacing + +> [ESLint rule][eslint-rules] to enforce spacing in return annotations in single-line comments. + +
+ +
+ + + +
+ +## Usage + +```javascript +var rule = require( '@stdlib/_tools/eslint/rules/doctest-annotation-spacing' ); +``` + +#### rule + +[ESLint rule][eslint-rules] to enforce spacing in return annotations in single-line comments. The rule checks `// returns` and `// =>` annotations (including `// e.g., returns` and `// e.g., =>` variants) and ensures: + +- Exactly 1 space between `//` and the annotation keyword +- The configured number of spaces after the annotation keyword (default: 1) + +**Bad** (too many spaces after `returns`): + +```text +var v = 3.14; +// returns 3.14 +``` + +**Bad** (no space before `=>`): + +```text +console.log( 'beep' ); +//=> 'beep' +``` + +**Bad** (too many spaces before `returns`): + +```text +var x = true; +// returns true +``` + +**Good**: + +```javascript +var v = 3.14; +// returns 3.14 + +console.log( 'beep' ); +// => 'beep' +``` + +## Options + +The rule accepts an options object with the following property: + +- **numSpaces**: number of spaces required after the annotation keyword. Default: `1`. + +```javascript +// With numSpaces: 2, the following would be valid: +var v = 3.14; +// returns 3.14 +``` + +Note: The spacing before the annotation keyword is always enforced to be exactly 1 space and is not configurable. + +
+ + + +
+ +## Notes + +- This rule only applies to single-line comments (starting with `//`). Multi-line comments (`/* ... */`) are ignored. + +- The rule matches the following patterns: + + - `// returns` + - `// =>` + - `// e.g., returns` + - `// e.g., =>` + +- The rule enforces two spacing requirements: + + - Exactly 1 space after `//` (not configurable) + - Configurable spacing after the keyword (default: 1 space) + +
+ + + +
+ +## Examples + + + +```javascript +var Linter = require( 'eslint' ).Linter; +var rule = require( '@stdlib/_tools/eslint/rules/doctest-annotation-spacing' ); + +var linter = new Linter(); +var result; +var code; + +code = [ + 'var v = foo();', + '// returns \'beep\'', + '', + 'console.log( bar() );', + '// => \'boop\'' +].join( '\n' ); + +linter.defineRule( 'doctest-annotation-spacing', rule ); + +result = linter.verify( code, { + 'rules': { + 'doctest-annotation-spacing': 'error' + } +}); +/* returns + [ + { + 'ruleId': 'doctest-annotation-spacing', + 'severity': 2, + 'message': 'Return annotation `returns` should be followed by 1 space(s). Found 13 space(s).', + 'line': 2, + 'column': 1, + 'nodeType': null, + 'endLine': 2, + 'endColumn': 31 + } + ] +*/ +``` + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/examples/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/examples/index.js new file mode 100644 index 000000000000..ca316938958b --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/examples/index.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 Linter = require( 'eslint' ).Linter; +var rule = require( './../lib' ); + +var linter = new Linter(); +var result; +var code; + +code = [ + 'var v = foo();', + '// returns \'beep\'', + '', + 'console.log( bar() );', + '// => \'boop\'' +].join( '\n' ); + +linter.defineRule( 'doctest-annotation-spacing', rule ); + +result = linter.verify( code, { + 'rules': { + 'doctest-annotation-spacing': 'error' + } +}); +console.log( result ); +/* => + [ + { + 'ruleId': 'doctest-annotation-spacing', + 'severity': 2, + 'message': 'Return annotation `returns` should be followed by 1 space(s). Found 13 space(s).', + 'line': 2, + 'column': 1, + 'nodeType': null, + 'endLine': 2, + 'endColumn': 31 + } + ] +*/ diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/defaults.json b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/defaults.json new file mode 100644 index 000000000000..5121dd2f5813 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/defaults.json @@ -0,0 +1,3 @@ +{ + "numSpaces": 1 +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/index.js new file mode 100644 index 000000000000..c5254a75db9d --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/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 to enforce spacing after return annotations in single-line comments. +* +* @module @stdlib/_tools/eslint/rules/doctest-annotation-spacing +* +* @example +* var rule = require( '@stdlib/_tools/eslint/rules/doctest-annotation-spacing' ); +* +* console.log( rule ); +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/main.js b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/main.js new file mode 100644 index 000000000000..fd0c0694301f --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/lib/main.js @@ -0,0 +1,194 @@ +/** +* @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 hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var copy = require( '@stdlib/utils/copy' ); +var DEFAULTS = require( './defaults.json' ); + + +// VARIABLES // + +/** +* Matches a single-line return annotation. +* +* Regular expression: `/^\/\/(\s*)(?:(e\.g\.,)\s*)?(returns|=>)(\s*)/` +* +* - `^` +* - match the beginning of the string +* +* - `\/\/` +* - match a `//` literal +* +* - `(\s*)` +* - capture zero or more whitespace characters (the spacing before the keyword) +* +* - `(?:(e\.g\.,)\s*)?` +* - optionally match the literal `e.g.,` followed by zero or more whitespace characters, capturing `e.g.,` +* +* - `(returns|=>)` +* - capture the annotation keyword `returns` or `=>` +* +* - `(\s*)` +* - capture zero or more whitespace characters (the spacing after the keyword) +* +* @constant +* @type {RegExp} +* @default /^\/\/(\s*)(?:(e\.g\.,)\s*)?(returns|=>)(\s*)/ +*/ +var RE_ANNOTATION = /^\/\/(\s*)(?:(e\.g\.,)\s*)?(returns|=>)(\s*)/; +var rule; + + +// FUNCTIONS // + +/** +* Rule for validating that return annotations have correct spacing. +* +* @param {Object} context - ESLint context +* @returns {Object} validators +*/ +function main( context ) { + var options; + var source; + var opts; + + opts = copy( DEFAULTS ); + options = context.options[ 0 ]; + if ( options ) { + if ( hasOwnProp( options, 'numSpaces' ) ) { + opts.numSpaces = options.numSpaces; + } + } + source = context.getSourceCode(); + + /** + * Reports the error message. + * + * @private + * @param {Object} loc - error location info + * @param {string} msg - error message + */ + function report( loc, msg ) { + context.report({ + 'node': null, + 'message': msg, + 'loc': loc + }); + } + + /** + * Checks whether return annotations in the current program have correct spacing. + * + * @private + * @param {ASTNode} node - node to examine + */ + function validate( node ) { + var comments; + var i; + + comments = source.getAllComments( node ); + for ( i = 0; i < comments.length; i++ ) { + checkComment( comments[ i ] ); + } + } + + /** + * Checks whether a comment is a return annotation and, if so, whether it has correct spacing. + * + * @private + * @param {Object} comment - comment to examine + */ + function checkComment( comment ) { + var spacingBefore; + var spacingAfter; + var expected; + var matches; + var keyword; + var prefix; + var text; + var msg; + + // Only check single-line comments: + if ( comment.type !== 'Line' ) { + return; + } + // Reconstruct the comment text with the leading slashes: + text = '//' + comment.value; + + matches = text.match( RE_ANNOTATION ); + if ( matches ) { + spacingBefore = matches[ 1 ].length; + prefix = matches[ 2 ] || ''; // 'e.g.,' or empty + keyword = matches[ 3 ]; // 'returns' or '=>' + spacingAfter = matches[ 4 ].length; + + // Check spacing before keyword (must be exactly 1 space): + if ( spacingBefore !== 1 ) { + if ( prefix ) { + msg = 'Return annotation `' + prefix + ' ' + keyword + '` should have exactly 1 space after `//`. Found ' + spacingBefore + ' space(s).'; + } else { + msg = 'Return annotation `' + keyword + '` should have exactly 1 space after `//`. Found ' + spacingBefore + ' space(s).'; + } + report( comment.loc, msg ); + } + // Check spacing after keyword (configurable): + expected = opts.numSpaces; + if ( spacingAfter !== expected ) { + msg = 'Return annotation `' + keyword + '` should be followed by ' + expected + ' space(s). Found ' + spacingAfter + ' space(s).'; + report( comment.loc, msg ); + } + } + } + + return { + 'Program': validate + }; +} + + +// MAIN // + +rule = { + 'meta': { + 'docs': { + 'description': 'enforce spacing after return annotations in single-line comments' + }, + 'schema': [ + { + 'type': 'object', + 'properties': { + 'numSpaces': { + 'type': 'integer', + 'minimum': 1 + } + }, + 'additionalProperties': false + } + ] + }, + 'create': main +}; + + +// EXPORTS // + +module.exports = rule; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/package.json new file mode 100644 index 000000000000..eba845cb3699 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/package.json @@ -0,0 +1,66 @@ +{ + "name": "@stdlib/_tools/eslint/rules/doctest-annotation-spacing", + "version": "0.0.0", + "description": "ESLint rule to enforce spacing after return annotations in single-line comments.", + "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" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "tools", + "tool", + "eslint", + "lint", + "custom", + "rules", + "rule", + "plugin", + "return", + "comment", + "annotation", + "spacing", + "returns", + "doctest" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/fixtures/invalid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/fixtures/invalid.js new file mode 100644 index 000000000000..62eec7469ab4 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/fixtures/invalid.js @@ -0,0 +1,233 @@ +/** +* @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; + +// Multiple spaces after `returns`: +test = { + 'code': [ + 'var p = boop();', + '// returns \'bip\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `returns` should be followed by 1 space(s). Found 13 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// Multiple spaces after `=>`: +test = { + 'code': [ + 'console.log( boop() );', + '// => \'bip\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `=>` should be followed by 1 space(s). Found 13 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// No space after `returns`: +test = { + 'code': [ + 'var v = foo();', + '// returns\'beep\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `returns` should be followed by 1 space(s). Found 0 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// No space after `=>`: +test = { + 'code': [ + 'console.log( foo() );', + '// =>\'beep\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `=>` should be followed by 1 space(s). Found 0 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// Multiple spaces after `e.g., returns`: +test = { + 'code': [ + 'var v = randn();', + '// e.g., returns 0.5363925252089496' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `returns` should be followed by 1 space(s). Found 4 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// Multiple spaces after `e.g., =>`: +test = { + 'code': [ + 'console.log( randn() );', + '// e.g., => 0.5363925252089496' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `=>` should be followed by 1 space(s). Found 4 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// Two spaces after `returns`: +test = { + 'code': [ + 'var v = foo();', + '// returns \'beep\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `returns` should be followed by 1 space(s). Found 2 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// Multiple invalid annotations in one file: +test = { + 'code': [ + 'var v = foo();', + '// returns \'beep\'', + '', + 'console.log( bar() );', + '// => \'boop\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `returns` should be followed by 1 space(s). Found 3 space(s).', + 'type': null + }, + { + 'message': 'Return annotation `=>` should be followed by 1 space(s). Found 3 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// Two spaces before `returns`: +test = { + 'code': [ + 'var v = foo();', + '// returns \'beep\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `returns` should have exactly 1 space after `//`. Found 2 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// No space before `returns`: +test = { + 'code': [ + 'var v = foo();', + '//returns \'beep\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `returns` should have exactly 1 space after `//`. Found 0 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// No space before `=>`: +test = { + 'code': [ + 'console.log( foo() );', + '//=> \'beep\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `=>` should have exactly 1 space after `//`. Found 0 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// Multiple spaces before `e.g., returns`: +test = { + 'code': [ + 'var v = randn();', + '// e.g., returns 0.5363925252089496' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `e.g., returns` should have exactly 1 space after `//`. Found 3 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + +// Both spacing errors (before and after): +test = { + 'code': [ + 'var v = foo();', + '// returns \'beep\'' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Return annotation `returns` should have exactly 1 space after `//`. Found 2 space(s).', + 'type': null + }, + { + 'message': 'Return annotation `returns` should be followed by 1 space(s). Found 2 space(s).', + 'type': null + } + ] +}; +invalid.push( test ); + + +// EXPORTS // + +module.exports = invalid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/fixtures/valid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/fixtures/valid.js new file mode 100644 index 000000000000..e62816b06264 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/fixtures/valid.js @@ -0,0 +1,124 @@ +/** +* @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; + +// Single space after `returns`: +test = { + 'code': [ + 'var v = foo();', + '// returns \'beep\'' + ].join( '\n' ) +}; +valid.push( test ); + +// Single space after `=>`: +test = { + 'code': [ + 'console.log( foo() );', + '// => \'beep\'' + ].join( '\n' ) +}; +valid.push( test ); + +// Single space after `e.g., returns`: +test = { + 'code': [ + 'var v = randn();', + '// e.g., returns 0.5363925252089496' + ].join( '\n' ) +}; +valid.push( test ); + +// Single space after `e.g., =>`: +test = { + 'code': [ + 'console.log( randn() );', + '// e.g., => 0.5363925252089496' + ].join( '\n' ) +}; +valid.push( test ); + +// Multiple return annotations with correct spacing: +test = { + 'code': [ + 'var isLowercase = require( \'./../lib\' );', + '', + 'var bool = isLowercase( \'hello\' );', + '// returns true', + '', + 'bool = isLowercase( \'\' );', + '// returns false', + '', + 'console.log( isLowercase( \'Hello\' ) );', + '// => false' + ].join( '\n' ) +}; +valid.push( test ); + +// Multi-line comments should be ignored (not single-line): +test = { + 'code': [ + 'var f = beep();', + '/* returns', + '{', + ' ...', + '}', + '*/' + ].join( '\n' ) +}; +valid.push( test ); + +// Block comments with `returns` should be ignored: +test = { + 'code': [ + 'var f = beep();', + '/* returns \'bip\' */' + ].join( '\n' ) +}; +valid.push( test ); + +// Comments without annotations are not affected: +test = { + 'code': [ + '// This is a regular comment', + 'var x = 5;' + ].join( '\n' ) +}; +valid.push( test ); + +// JSDoc comments are not affected: +test = { + 'code': [ + '/**', + '* @returns {boolean} Boolean indicating whether the input is lowercase.', + '*/', + 'function isLowercase( str ) {', + ' return str === str.toLowerCase();', + '}' + ].join( '\n' ) +}; +valid.push( test ); + + +// EXPORTS // + +module.exports = valid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/test.js b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/test.js new file mode 100644 index 000000000000..2d46aeef8096 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/test/test.js @@ -0,0 +1,121 @@ +/** +* @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' ); + + +// 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 function positively validates code with correct spacing in return annotations', function test( t ) { + var tester = new RuleTester(); + + try { + tester.run( 'doctest-annotation-spacing', rule, { + 'valid': valid, + 'invalid': [] + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +}); + +tape( 'the function negatively validates code with incorrect spacing in return annotations', function test( t ) { + var tester = new RuleTester(); + + try { + tester.run( 'doctest-annotation-spacing', rule, { + 'valid': [], + 'invalid': invalid + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +}); + +tape( 'the function supports custom number of spaces via configuration', function test( t ) { + var customInvalid; + var customValid; + var tester; + + tester = new RuleTester(); + + // With numSpaces: 2, two spaces should be valid + customValid = [ + { + 'code': [ + 'var v = foo();', + '// returns \'beep\'' + ].join( '\n' ), + 'options': [{ + 'numSpaces': 2 + }] + } + ]; + + // With numSpaces: 2, one space should be invalid + customInvalid = [ + { + 'code': [ + 'var v = foo();', + '// returns \'beep\'' + ].join( '\n' ), + 'options': [{ + 'numSpaces': 2 + }], + 'errors': [ + { + 'message': 'Return annotation `returns` should be followed by 2 space(s). Found 1 space(s).', + 'type': null + } + ] + } + ]; + + try { + tester.run( 'doctest-annotation-spacing', rule, { + 'valid': customValid, + 'invalid': customInvalid + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +}); From 850c135a79c9f672de786936698a29ac08d0c63e Mon Sep 17 00:00:00 2001 From: Philipp Burckhardt Date: Fri, 5 Dec 2025 23:48:15 -0600 Subject: [PATCH 2/4] docs: use JavaScript code blocks in README examples Also register the rule in the ESLint plugin namespace. --- 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: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - 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 --- --- .../rules/doctest-annotation-spacing/README.md | 12 +++++++++--- .../@stdlib/_tools/eslint/rules/lib/index.js | 9 +++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md index bc54c87290e4..f238a7aec8ed 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md @@ -45,21 +45,27 @@ var rule = require( '@stdlib/_tools/eslint/rules/doctest-annotation-spacing' ); **Bad** (too many spaces after `returns`): -```text + + +```javascript var v = 3.14; // returns 3.14 ``` **Bad** (no space before `=>`): -```text + + +```javascript console.log( 'beep' ); //=> 'beep' ``` **Bad** (too many spaces before `returns`): -```text + + +```javascript var x = true; // returns true ``` 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..c6487369352f 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js @@ -54,6 +54,15 @@ setReadOnly( rules, 'capitalized-comments', require( '@stdlib/_tools/eslint/rule */ setReadOnly( rules, 'doctest', require( '@stdlib/_tools/eslint/rules/doctest' ) ); +/** +* @name doctest-annotation-spacing +* @memberof rules +* @readonly +* @type {Function} +* @see {@link module:@stdlib/_tools/eslint/rules/doctest-annotation-spacing} +*/ +setReadOnly( rules, 'doctest-annotation-spacing', require( '@stdlib/_tools/eslint/rules/doctest-annotation-spacing' ) ); + /** * @name doctest-marker * @memberof rules From b79f72fb12e6543b5632a948877fc6e3f8efe388 Mon Sep 17 00:00:00 2001 From: Athan Date: Sun, 7 Dec 2025 01:29:03 -0800 Subject: [PATCH 3/4] docs: update example Signed-off-by: Athan --- .../eslint/rules/doctest-annotation-spacing/README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md index f238a7aec8ed..bde1835ca2bc 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/README.md @@ -131,10 +131,8 @@ var Linter = require( 'eslint' ).Linter; var rule = require( '@stdlib/_tools/eslint/rules/doctest-annotation-spacing' ); var linter = new Linter(); -var result; -var code; -code = [ +var code = [ 'var v = foo();', '// returns \'beep\'', '', @@ -144,7 +142,7 @@ code = [ linter.defineRule( 'doctest-annotation-spacing', rule ); -result = linter.verify( code, { +var result = linter.verify( code, { 'rules': { 'doctest-annotation-spacing': 'error' } From bfa5a502453c6c8e8ac7093aed444a38a4dc8b90 Mon Sep 17 00:00:00 2001 From: Athan Date: Sun, 7 Dec 2025 01:30:48 -0800 Subject: [PATCH 4/4] docs: update example Signed-off-by: Athan --- .../rules/doctest-annotation-spacing/examples/index.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/examples/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/examples/index.js index ca316938958b..a90ea58e02da 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/examples/index.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/doctest-annotation-spacing/examples/index.js @@ -22,10 +22,8 @@ var Linter = require( 'eslint' ).Linter; var rule = require( './../lib' ); var linter = new Linter(); -var result; -var code; -code = [ +var code = [ 'var v = foo();', '// returns \'beep\'', '', @@ -35,7 +33,7 @@ code = [ linter.defineRule( 'doctest-annotation-spacing', rule ); -result = linter.verify( code, { +var result = linter.verify( code, { 'rules': { 'doctest-annotation-spacing': 'error' }