diff --git a/etc/eslint/plugins/typescript.js b/etc/eslint/plugins/typescript.js index 5553eb157e03..e030322a9d7b 100644 --- a/etc/eslint/plugins/typescript.js +++ b/etc/eslint/plugins/typescript.js @@ -30,7 +30,10 @@ var plugins = [ 'eslint-plugin-jsdoc', // Required for TypeScript support: - '@typescript-eslint' + '@typescript-eslint', + + // Custom stdlib rules: + 'stdlib' ]; diff --git a/etc/eslint/rules/typescript.js b/etc/eslint/rules/typescript.js index 1639beb44f67..1cdfa733846e 100644 --- a/etc/eslint/rules/typescript.js +++ b/etc/eslint/rules/typescript.js @@ -2712,6 +2712,17 @@ rules[ 'yoda' ] = 'error'; */ rules[ 'expect-type/expect' ] = 'error'; +/** +* Ensures return annotations in TSDoc examples match the actual output. +* +* @name stdlib/tsdoc-declarations-doctest +* @memberof rules +* @type {string} +* @default 'error' +* @see {@link module:@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest} +*/ +rules[ 'stdlib/tsdoc-declarations-doctest' ] = 'error'; + // EXPORTS // 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 a83887850934..817b943efba0 100644 --- a/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/lib/index.js @@ -1071,6 +1071,15 @@ setReadOnly( rules, 'section-headers', require( '@stdlib/_tools/eslint/rules/sec */ setReadOnly( rules, 'ternary-condition-parentheses', require( '@stdlib/_tools/eslint/rules/ternary-condition-parentheses' ) ); +/** +* @name tsdoc-declarations-doctest +* @memberof rules +* @readonly +* @type {Function} +* @see {@link module:@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest} +*/ +setReadOnly( rules, 'tsdoc-declarations-doctest', require( '@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest' ) ); + /** * @name uppercase-required-constants * @memberof rules diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/README.md b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/README.md new file mode 100644 index 000000000000..64c35a1ed5e0 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/README.md @@ -0,0 +1,180 @@ + + +# tsdoc-declarations-doctest + +> [ESLint rule][eslint-rules] to ensure that return annotations in TSDoc examples match the actual output in TypeScript declaration files (`*.d.ts`). + +
+ +
+ + + +
+ +## Usage + +```javascript +var rule = require( '@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest' ); +``` + +#### rule + +[ESLint rule][eslint-rules] to ensure that return annotations in TSDoc examples match the actual output in TypeScript declaration files (`*.d.ts`). + +**Bad**: + + + +```typescript +/** +* Adds two numbers. +* +* @param x - first number +* @param y - second number +* @returns sum of x and y +* +* @example +* var result = add( 2, 3 ); +* // returns 6 +*/ +declare function add( x: number, y: number ): number; +``` + +**Good**: + +```typescript +/** +* Adds two numbers. +* +* @param x - first number +* @param y - second number +* @returns sum of x and y +* +* @example +* var result = add( 2, 3 ); +* // returns 5 +*/ +declare function add( x: number, y: number ): number; +``` + +
+ + + +
+ +## Notes + +- Return annotations may start with `returns`, `throws`, or `=>`. `returns` follow variable declarations or assignment expressions, whereas `=>` follow expression-only forms including `console.log` calls. +- The rule validates `@example` blocks in TSDoc comments within `*.d.ts` files by resolving the corresponding implementation via the nearest `package.json` file in the same or a parent directory and using its `main` field. +- The rule skips validation if the `package.json` file cannot be found or if the resolved implementation cannot be loaded. +- Examples are executed in a sandboxed VM context with limited globals for security. +- This rule is specifically designed for TypeScript declaration files and will only process files with a `*.d.ts` filename extension. + +
+ + + +
+ +## Examples + + + +```javascript +var Linter = require( 'eslint' ).Linter; +var parser = require( '@typescript-eslint/parser' ); +var rule = require( '@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest' ); + +var linter = new Linter(); + +// Register the TypeScript parser and ESLint rule: +linter.defineParser( '@typescript-eslint/parser', parser ); +linter.defineRule( 'tsdoc-declarations-doctest', rule ); + +// Generate our source code with incorrect return annotation: +var code = [ + '/**', + '* Returns the absolute value of a number.', + '*', + '* @param x - input value', + '* @returns absolute value', + '*', + '* @example', + '* var result = abs( -3 );', + '* // returns 2', + '*/', + 'declare function abs( x: number ): number;', + '', + 'export = abs;' +].join( '\n' ); + +// Lint the code: +var result = linter.verify( code, { + 'parser': '@typescript-eslint/parser', + 'parserOptions': { + 'ecmaVersion': 2018, + 'sourceType': 'module' + }, + 'rules': { + 'tsdoc-declarations-doctest': 'error' + } +}, { + 'filename': '/path/to/project/lib/node_modules/@stdlib/math/base/special/abs/docs/types/index.d.ts' +}); +/* returns + [ + { + 'ruleId': 'tsdoc-declarations-doctest', + 'severity': 2, + 'message': 'Displayed return value is `2`, but expected `3` instead', + 'line': 9, + 'column': 1, + 'nodeType': null, + 'endLine': 10, + 'endColumn': 37 + } + ] +*/ +``` + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/examples/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/examples/index.js new file mode 100644 index 000000000000..dbee7790d027 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/examples/index.js @@ -0,0 +1,76 @@ +/** +* @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 parser = require( '@typescript-eslint/parser' ); +var rule = require( './../lib' ); + +var linter = new Linter(); + +// Register the TypeScript parser and ESLint rule: +linter.defineParser( '@typescript-eslint/parser', parser ); +linter.defineRule( 'tsdoc-declarations-doctest', rule ); + +// Generate our source code with incorrect return annotation: +var code = [ + '/**', + '* Returns the absolute value of a number.', + '*', + '* @param x - input value', + '* @returns absolute value', + '*', + '* @example', + '* var result = abs( -3 );', + '* // returns 2', + '*/', + 'declare function abs( x: number ): number;', + '', + 'export = abs;' +].join( '\n' ); + +// Lint the code: +var result = linter.verify( code, { + 'parser': '@typescript-eslint/parser', + 'parserOptions': { + 'ecmaVersion': 2018, + 'sourceType': 'module' + }, + 'rules': { + 'tsdoc-declarations-doctest': 'error' + } +}, { + 'filename': 'lib/node_modules/@stdlib/math/base/special/abs/docs/types/index.d.ts' +}); + +console.log( result ); +/* => + [ + { + 'ruleId': 'tsdoc-declarations-doctest', + 'severity': 2, + 'message': 'Displayed return value is `2`, but expected `3` instead', + 'line': 9, + 'column': 1, + 'nodeType': null, + 'endLine': 10, + 'endColumn': 37 + } + ] +*/ diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/add_package_to_scope.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/add_package_to_scope.js new file mode 100644 index 000000000000..88b5fc3b2401 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/add_package_to_scope.js @@ -0,0 +1,84 @@ +/** +* @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 // + +// Regular expression to match function declarations such as "declare function abs( x: number ): number;" (captures function name): +var RE_DECLARE_FUNCTION = /declare\s+function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*[<(]/; + +// Regular expression to match variable declarations such as "declare var someVar: SomeType;" (captures variable name): +var RE_DECLARE_VAR = /declare\s+var\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/; + +// Regular expression to match class declarations such as "declare class Complex64Array {" (captures class name): +var RE_DECLARE_CLASS = /declare\s+class\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s/; + +// Regular expression to match const declarations such as "declare const PI: number;" (captures constant name): +var RE_DECLARE_CONST = /declare\s+const\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/; + +// Regular expression to match variable declarations with interface types such as "declare var ctor: Int32Vector;" (captures variable name and interface name): +var RE_DECLARE_VAR_INTERFACE = /declare\s+var\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:\s*([A-Z][a-zA-Z0-9_$]*)/; + + +// MAIN // + +/** +* Adds a package export to the scope based on TypeScript declarations. +* +* @private +* @param {Object} scope - VM scope object to add the package export to +* @param {*} pkg - package export value to be added to scope +* @param {string} sourceText - TypeScript declaration source text to parse for identifier names +*/ +function addPackageToScope( scope, pkg, sourceText ) { + var interfaceMatch; + var namespaceMatch; + var pkgType; + var match; + + pkgType = typeof pkg; + if ( pkgType === 'function' ) { + match = sourceText.match( RE_DECLARE_FUNCTION ) || sourceText.match( RE_DECLARE_VAR ) || sourceText.match( RE_DECLARE_CLASS ); // eslint-disable-line max-len + if ( match ) { + scope[ match[1] ] = pkg; + } + interfaceMatch = sourceText.match( RE_DECLARE_VAR_INTERFACE ); + if ( interfaceMatch ) { + // Make the function available under both the variable and interface names: + scope[ interfaceMatch[1] ] = pkg; // e.g., ctor + scope[ interfaceMatch[2] ] = pkg; // e.g., Int32Vector + } + } else { + if ( pkgType === 'object' && pkg !== null ) { + namespaceMatch = sourceText.match( RE_DECLARE_VAR_INTERFACE ); + if ( namespaceMatch ) { + scope[ namespaceMatch[1] ] = pkg; + } + } + match = sourceText.match( RE_DECLARE_CONST ); + if ( match ) { + scope[ match[1] ] = pkg; + } + } +} + + +// EXPORTS // + +module.exports = addPackageToScope; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/create_vm_scope.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/create_vm_scope.js new file mode 100644 index 000000000000..3d8b054caa0c --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/create_vm_scope.js @@ -0,0 +1,84 @@ +/** +* @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 proc = require( 'process' ); +var format = require( 'util' ).format; +var Buffer = require( '@stdlib/buffer/ctor' ); +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var windowShim = require( './window.js' ); + + +// FUNCTIONS // + +/** +* Shim for `console.log` function that returns the logged data instead of printing it to `stdout`. +* +* @private +* @param {*} data - data to be logged +* @param {...*} [args] - substitution values +* @returns {*} formatted string if first argument is string, otherwise first argument +*/ +function log( data ) { + if ( isString( data ) ) { + return format.apply( null, arguments ); + } + return data; +} + + +// MAIN // + +/** +* Creates a VM execution scope with necessary globals. +* +* @private +* @param {string} dir - directory path +* @param {string} filename - file name +* @returns {Object} VM scope object +*/ +function createVMScope( dir, filename ) { + return { + 'require': require, + 'exports': exports, // eslint-disable-line node/exports-style + 'module': module, + 'process': proc, + 'setTimeout': setTimeout, + 'clearTimeout': clearTimeout, + 'setInterval': setInterval, + 'clearInterval': clearInterval, + 'window': windowShim, + 'Buffer': Buffer, + '__dirname': dir, + '__filename': filename, + 'console': { + 'dir': log, + 'error': log, + 'log': log, + 'warn': log + } + }; +} + + +// EXPORTS // + +module.exports = createVMScope; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/index.js new file mode 100644 index 000000000000..2888b085c545 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/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 ensure return annotations in TypeScript declaration examples match the actual output. +* +* @module @stdlib/_tools/eslint/rules/tsdoc-declarations-doctest +* +* @example +* var rule = require( '@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest' ); +* +* console.log( rule ); +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/main.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/main.js new file mode 100644 index 000000000000..48e7ea182e5c --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/main.js @@ -0,0 +1,497 @@ +/** +* @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. +*/ + +/* eslint-disable max-len, max-lines */ + +'use strict'; + +// MODULES // + +var vm = require( 'vm' ); +var resolve = require( 'path' ).resolve; +var readFileSync = require( 'fs' ).readFileSync; // eslint-disable-line node/no-sync +var logger = require( 'debug' ); +var resolveParentPath = require( '@stdlib/fs/resolve-parent-path' ).sync; +var dirname = require( '@stdlib/utils/dirname' ); +var isNull = require( '@stdlib/assert/is-null' ); +var isNumber = require( '@stdlib/assert/is-number' ); +var contains = require( '@stdlib/assert/contains' ); +var replace = require( '@stdlib/string/replace' ); +var endsWith = require( '@stdlib/string/ends-with' ); +var trim = require( '@stdlib/string/trim' ); +var reEOL = require( '@stdlib/regexp/eol' ); +var escapeRegExpString = require( '@stdlib/utils/escape-regexp-string' ); +var objectKeys = require( '@stdlib/utils/keys' ); +var tryRequire = require( '@stdlib/utils/try-require' ); +var compareValues = require( '@stdlib/_tools/doctest/compare-values' ); +var createAnnotationValue = require( '@stdlib/_tools/doctest/create-annotation-value' ); +var createVMScope = require( './create_vm_scope.js' ); +var addPackageToScope = require( './add_package_to_scope.js' ); +var SCOPE_DEFAULTS = require( './scope_defaults.json' ); + + +// VARIABLES // + +var debug = logger( 'tsdoc-doctest' ); +var RE_TSDOC = /\/\*\*[\s\S]+?\*\//g; +var RE_EXAMPLE = /@example\s*([\s\S]*?)(?=\n\s*@\w|\*\/|$)/g; +var RE_ANNOTATION = /(?:\n|^)(?:var|let|const)? ?([a-zA-Z0-9._]+) ?=?[^;]*;\n\/\/ ?(returns|([A-Za-z][A-Za-z_0-9]*)? ?=>|throws) ?([\s\S]*?)(?=\n|$)/g; +var RE_COMMENT_PREFIX = /^\s*\*\s?/gm; +var DEFAULT_ERROR_LOC = { + 'start': { + 'line': 1, + 'column': 0 + }, + 'end': { + 'line': 1, + 'column': 0 + } +}; +var regexCache = {}; +var lineCountCache = {}; +var rule; + + +// FUNCTIONS // + +/** +* Gets or creates a cached regex for finding return annotations. +* +* @private +* @param {string} annotationType - type of annotation (returns, throws, etc.) +* @param {string} value - expected value +* @returns {RegExp} compiled regular expression +*/ +function getAnnotationRegex( annotationType, value ) { + var escapedValue; + var pattern; + var key; + + escapedValue = escapeRegExpString( value ); + key = annotationType + '::' + escapedValue; + + if ( !regexCache[ key ] ) { + pattern = '// ' + annotationType + '\\s+' + escapedValue; + regexCache[ key ] = new RegExp( pattern ); + } + return regexCache[ key ]; +} + +/** +* Counts the number of lines in the given string. +* +* @private +* @param {string} str - input string +* @returns {number} number of lines +*/ +function countLines( str ) { + var lines; + + // Use cached result if available + if ( lineCountCache[ str ] ) { + return lineCountCache[ str ]; + } + lines = str.split( reEOL() ); + lineCountCache[ str ] = lines.length - 1; + return lineCountCache[ str ]; +} + +/** +* Searches for a variable in scope matching the expected value. +* +* @private +* @param {Object} scope - VM scope +* @param {*} expected - expected value to search for +* @returns {string} variable name or `?` if no match found +*/ +function findName( scope, expected ) { + var keys = objectKeys( scope ); + var key; + var i; + for ( i = 0; i < keys.length; i++ ) { + key = keys[ i ]; + if ( + !contains( SCOPE_DEFAULTS, key ) && + compareValues( scope[ key ], expected ) === null + ) { + return key; + } + } + return '?'; +} + +/** +* Resolves the implementation path from the nearest parent `package.json`. +* +* @private +* @param {string} filepath - TypeScript declaration file path +* @returns {(string|null)} resolved implementation path or null if not found +*/ +function resolveImplementationPath( filepath ) { + var mainPath; + var pkgJSON; + var pkgPath; + var pkgDir; + var opts; + + // Find the nearest package.json: + opts = { + 'dir': dirname( resolve( filepath ) ) + }; + pkgPath = resolveParentPath( 'package.json', opts ); + if ( !pkgPath ) { + debug( 'Could not find package.json for: ' + filepath ); + return null; + } + + // Read and parse package.json: + try { + pkgJSON = JSON.parse( readFileSync( pkgPath, 'utf8' ) ); + } catch ( err ) { + debug( 'Could not read/parse package.json: ' + pkgPath + '. Error: ' + err.message ); + return null; + } + + // Get the main entry point: + mainPath = pkgJSON.main || './lib'; + pkgDir = dirname( pkgPath ); + return resolve( pkgDir, mainPath ); +} + +/** +* Cleans TSDoc comment by removing comment prefixes. +* +* @private +* @param {string} comment - TSDoc comment +* @returns {string} cleaned comment +*/ +function cleanTSDocComment( comment ) { + // Remove opening /** and closing */ + var cleaned = replace( replace( comment, /^\/\*\*/, '' ), /\*\/$/, '' ); + + // Remove * at the beginning of lines + return replace( cleaned, RE_COMMENT_PREFIX, '' ); +} + +/** +* Processes a single example code block, finding and validating annotations. +* +* @private +* @param {string} code - example code +* @param {number} commentIdx - comment index +* @param {Array} comments - all comments +* @param {Object} scope - VM execution scope +* @param {Function} report - error reporting function +* @param {Object} opts - options object +* @param {Object} sourceCode - source code object +*/ +function processExampleCode( code, commentIdx, comments, scope, report, opts, sourceCode ) { + var returnAnnotationPattern; + var valueStartInAnnotation; + var commentStartIdx; + var annotationMatch; + var annotationStart; + var exampleStartIdx; + var annotationEnd; + var intermediary; + var replacement; + var exampleIdx; + var remaining; + var expected; + var codeIdx; + var actual; + var last; + var line; + var type; + var out; + var loc; + var msg; + var arr; + + last = 0; + RE_ANNOTATION.lastIndex = 0; + try { + arr = RE_ANNOTATION.exec( code ); + while ( !isNull( arr ) ) { + intermediary = code.substring( last, arr.index ); + last = arr.index + arr[ 0 ].length; + if ( intermediary ) { + vm.runInContext( intermediary, scope ); + } + + // Calculate line of current code chunk within the comment: + commentStartIdx = sourceCode.text.indexOf( comments[ commentIdx ] ); + + // Find the annotation in the original comment: + returnAnnotationPattern = getAnnotationRegex( arr[ 2 ], arr[ 4 ] ); + annotationMatch = comments[ commentIdx ].match( returnAnnotationPattern ); + + if ( !annotationMatch ) { + continue; + } + + codeIdx = comments[ commentIdx ].indexOf( annotationMatch[ 0 ] ); + line = countLines( sourceCode.text.substring( 0, commentStartIdx + codeIdx ) ) + 1; + loc = { + 'start': { + 'line': line, + 'column': 0 + }, + 'end': { + 'line': line + countLines( arr[ 0 ] ), + 'column': arr[ 0 ].length + } + }; + + // Run code preceding return annotation and capture result: + try { + out = vm.runInContext( arr[ 0 ], scope ); + + // Determine actual value based on annotation form: + if ( arr[ 3 ] ) { + // Expression form with named variable: someExpression; // variable => value + actual = vm.runInContext( arr[ 3 ], scope ); + } else if ( arr[ 1 ] && arr[ 1 ] !== 'console.log' && !arr[ 2 ].match( /^=>/ ) ) { + // Assignment form: var x = expression; // returns value + actual = scope[ arr[ 1 ] ]; + } else { + // Bare expression form (incl. console.log): someExpression; // => value + actual = out; + } + expected = arr[ 4 ]; + msg = compareValues( actual, expected ); + if ( msg ) { + opts.includeDecimal = isNumber( actual ) && contains( expected, '.' ); + replacement = createAnnotationValue( actual, opts ); + + // Find the position of the return value in the annotation: + valueStartInAnnotation = annotationMatch[ 0 ].indexOf( arr[ 4 ] ); + loc.range = [ + // Position of arr[4] start in source text: + commentStartIdx + codeIdx + valueStartInAnnotation, + + // Position of arr[4] end in source text: + commentStartIdx + codeIdx + valueStartInAnnotation + arr[ 4 ].length + ]; + report( loc, msg, replacement ); + } + } catch ( err ) { + type = '<'+err.name+'>'; + if ( arr[ 2 ] !== 'throws' ) { + if ( arr[ 3 ] ) { + msg = 'Encountered an error: `'+err.message+'`.'; + } else { + msg = 'Encountered an error while running code: `'+err.message+'`. '; + msg += 'Did you mean to include a `// throws '+type+'` annotation instead of `// '+arr[ 2 ]+' '+arr[ 4 ]+'`?'; + } + } + else if ( arr[ 4 ] !== type ) { + msg = 'Code should have a `// throws '+type+'` annotation, but received: `// '+arr[ 2 ]+' '+arr[ 4 ]+'`'; + } + if ( msg ) { + replacement = ( arr[ 3 ] ) ? findName( scope, arr[ 4 ] ) + ' => ' + arr[ 4 ] : 'throws '+type; + + // Find annotation part in the match (after "// "): + annotationStart = arr[ 0 ].indexOf( '// ' ) + 3; + annotationEnd = arr[ 0 ].length; + loc.range = [ + commentStartIdx + codeIdx + annotationStart, + commentStartIdx + codeIdx + annotationEnd + ]; + report( loc, msg, replacement ); + } + } + arr = RE_ANNOTATION.exec( code ); + } + + remaining = code.substring( last ); + if ( remaining ) { + vm.runInContext( remaining, scope ); + } + } catch ( err ) { + // Calculate the line number for the example that caused the error... + exampleStartIdx = sourceCode.text.indexOf( comments[ commentIdx ] ); + exampleIdx = comments[ commentIdx ].indexOf( code ); + line = countLines( sourceCode.text.substring( 0, exampleStartIdx + exampleIdx ) ) + 1; + loc = { + 'start': { + 'line': line, + 'column': 0 + }, + 'end': { + 'line': line + countLines( code ), + 'column': 0 + } + }; + + // Always report errors so programmer errors are not swallowed: + report( loc, 'Encountered an error while running example code: '+err.message ); + } +} + +/** +* Rule for validating that return annotations in TypeScript declaration examples match the actual output. +* +* @param {Object} context - ESLint context +* @returns {Object} validators +*/ +function main( context ) { + var sourceCode; + var filename; + var dir; + + sourceCode = context.getSourceCode(); + filename = context.getFilename(); + + // Only process TypeScript declaration files: + if ( !endsWith( filename, '.d.ts' ) ) { + return {}; + } + + dir = dirname( filename ); + + /** + * Reports the error message. + * + * @private + * @param {Object} loc - error location info + * @param {string} msg - error message + * @param {string} replacement - fixed return annotation + */ + function report( loc, msg, replacement ) { + var result = { + 'message': msg, + 'loc': loc + }; + if ( replacement ) { + result.fix = fix; + } + context.report( result ); + + /** + * Applies a fix to the offending code. + * + * @private + * @param {Object} fixer - object to apply a fix + * @returns {Object} fixing object + */ + function fix( fixer ) { + return fixer.replaceTextRange( loc.range, replacement ); + } + } + + /** + * Validates examples in TSDoc comments. + * + * @private + */ + function validate() { + var implPath; + var comments; + var examples; + var cleaned; + var example; + var comment; + var scope; + var opts; + var code; + var pkg; + var i; + var j; + + // Clear caches to prevent memory leaks: + regexCache = {}; + lineCountCache = {}; + + // Resolve implementation path from nearest package.json: + implPath = resolveImplementationPath( filename ); + if ( !implPath ) { + debug( 'Could not resolve implementation path from package.json for: ' + filename ); + report( DEFAULT_ERROR_LOC, 'Could not resolve implementation path from package.json for this declaration file.' ); + return; + } + + // Try to load the implementation directly: + pkg = tryRequire( implPath ); + if ( pkg instanceof Error ) { + debug( 'Could not load implementation: ' + implPath + '. Error: ' + pkg.message ); + report( DEFAULT_ERROR_LOC, 'Could not load implementation: '+implPath+' ('+pkg.message+').' ); + return; + } + + // Get all TSDoc comments: + comments = sourceCode.text.match( RE_TSDOC ); + if ( !comments ) { + return; + } + + // Create a single VM scope and context for all examples: + scope = createVMScope( dir, filename ); + addPackageToScope( scope, pkg, sourceCode.text ); + vm.createContext( scope ); + + opts = { + 'includeDecimal': false + }; + + for ( i = 0; i < comments.length; i++ ) { + comment = comments[ i ]; + cleaned = cleanTSDocComment( comment ); + + // Extract @example blocks: + RE_EXAMPLE.lastIndex = 0; + examples = []; + example = RE_EXAMPLE.exec( cleaned ); + while ( example !== null ) { + examples.push( example[ 1 ] ); + example = RE_EXAMPLE.exec( cleaned ); + } + + for ( j = 0; j < examples.length; j++ ) { + code = trim( examples[ j ] ); + + // Process the example code and validate annotations (reusing VM context): + processExampleCode( code, i, comments, scope, report, opts, sourceCode ); + } + } + } + + return { + 'Program': validate + }; +} + + +// MAIN // + +rule = { + 'meta': { + 'type': 'problem', + 'docs': { + 'description': 'ensure return annotations in TSDoc examples match the actual output' + }, + 'fixable': 'code', + 'schema': [] + }, + 'create': main +}; + + +// EXPORTS // + +module.exports = rule; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/scope_defaults.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/scope_defaults.json new file mode 100644 index 000000000000..fab6c5ea05dc --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/scope_defaults.json @@ -0,0 +1,15 @@ +[ + "require", + "exports", + "module", + "process", + "setTimeout", + "clearTimeout", + "setInterval", + "clearInterval", + "window", + "Buffer", + "__dirname", + "__filename", + "console" +] diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/window.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/window.js new file mode 100644 index 000000000000..ce9936203e42 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/lib/window.js @@ -0,0 +1,35 @@ +/** +* @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 noop = require( '@stdlib/utils/noop' ); + + +// MAIN // + +var shim = { + 'open': noop +}; + + +// EXPORTS // + +module.exports = shim; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/package.json new file mode 100644 index 000000000000..ec5c7edfc07a --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/package.json @@ -0,0 +1,54 @@ +{ + "name": "@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest", + "version": "0.0.0", + "description": "ESLint rule to ensure return annotations in TSDoc examples match the actual output.", + "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" + } + ], + "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", + "rule", + "doctest", + "tsdoc", + "typescript" + ], + "__stdlib__": { + "envs": { + "node": true + } + } +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/invalid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/invalid.js new file mode 100644 index 000000000000..eb567e378352 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/invalid.js @@ -0,0 +1,258 @@ +/** +* @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 join = require( 'path' ).join; + + +// VARIABLES // + +var invalid = []; +var test; + + +// TESTS // + +test = { + 'code': [ + '/**', + '* Returns the absolute value.', + '*', + '* @param x - input value', + '* @returns absolute value', + '*', + '* @example', + '* var v = abs( -1.0 );', + '* // returns 2.0', + '*/', + 'declare function abs( x: number ): number;', + '', + 'export = abs;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/math/base/special/abs/docs/types/index.d.ts' ), + 'output': [ + '/**', + '* Returns the absolute value.', + '*', + '* @param x - input value', + '* @returns absolute value', + '*', + '* @example', + '* var v = abs( -1.0 );', + '* // returns 1', + '*/', + 'declare function abs( x: number ): number;', + '', + 'export = abs;' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Displayed return value is `2.0`, but expected `1` instead', + 'type': null + } + ] +}; +invalid.push( test ); + +test = { + 'code': [ + '/**', + '* Abbreviated Int32Vector example (invalid).', + '*', + '* @example', + "* var numel = require( '@stdlib/ndarray/numel' );", + '*', + '* var arr = new Int32Vector();', + '* // returns ', + '*', + '* var len = numel( arr );', + '* // returns 1', + '*/', + 'declare var ctor: Int32Vector;', + '', + 'export = ctor;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/ndarray/vector/int32/docs/types/index.d.ts' ), + 'output': [ + '/**', + '* Abbreviated Int32Vector example (invalid).', + '*', + '* @example', + "* var numel = require( '@stdlib/ndarray/numel' );", + '*', + '* var arr = new Int32Vector();', + '* // returns ', + '*', + '* var len = numel( arr );', + '* // returns 0', + '*/', + 'declare var ctor: Int32Vector;', + '', + 'export = ctor;' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Displayed return value is `1`, but expected `0` instead', + 'type': null + } + ] +}; +invalid.push( test ); + +test = { + 'code': [ + '/**', + '* Returns the square root.', + '*', + '* @param x - input value', + '* @returns square root', + '*', + '* @example', + '* var v = sqrt( 4.0 );', + '* // returns 3.0', + '*', + '* @example', + '* var v = sqrt( 9.0 );', + '* // returns 3.0', + '*/', + 'declare function sqrt( x: number ): number;', + '', + 'export = sqrt;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/math/base/special/sqrt/docs/types/index.d.ts' ), + 'output': [ + '/**', + '* Returns the square root.', + '*', + '* @param x - input value', + '* @returns square root', + '*', + '* @example', + '* var v = sqrt( 4.0 );', + '* // returns 2', + '*', + '* @example', + '* var v = sqrt( 9.0 );', + '* // returns 3.0', + '*/', + 'declare function sqrt( x: number ): number;', + '', + 'export = sqrt;' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Displayed return value is `3.0`, but expected `2` instead', + 'type': null + } + ] +}; +invalid.push( test ); + +test = { + 'code': [ + '/**', + '* The mathematical constant pi.', + '*', + '* @example', + '* var pi = PI;', + '* // returns 3.14', + '*/', + 'declare const PI: number;', + '', + 'export = PI;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/constants/float64/pi/docs/types/index.d.ts' ), + 'output': [ + '/**', + '* The mathematical constant pi.', + '*', + '* @example', + '* var pi = PI;', + '* // returns ~3.142', + '*/', + 'declare const PI: number;', + '', + 'export = PI;' + ].join( '\n' ), + 'errors': [ + { + 'message': 'Displayed return value is `3.14`, but expected `3.141592653589793` instead', + 'type': null + } + ] +}; +invalid.push( test ); + +test = { + 'code': [ + '/**', + '* Evaluates the exponential function.', + '*', + '* @param b - base', + '* @param x - exponent', + '* @returns function value', + '*', + '* @example', + '* console.log( pow( 3.0, 2.0 ) );', + '* // => 8.0', + '*', + '* @example', + '* console.log( pow( 2.0, 2.0 ) );', + '* // => 4.0', + '*/', + 'declare function pow( b: number, x: number ): number;', + '', + 'export = pow;' + ].join( '\n' ), + 'output': [ + '/**', + '* Evaluates the exponential function.', + '*', + '* @param b - base', + '* @param x - exponent', + '* @returns function value', + '*', + '* @example', + '* console.log( pow( 3.0, 2.0 ) );', + '* // => 9', + '*', + '* @example', + '* console.log( pow( 2.0, 2.0 ) );', + '* // => 4.0', + '*/', + 'declare function pow( b: number, x: number ): number;', + '', + 'export = pow;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/math/base/special/pow/docs/types/index.d.ts' ), + 'errors': [ + { + 'message': 'Displayed return value is `8.0`, but expected `9` instead', + 'type': null + } + ] +}; +invalid.push( test ); + + +// EXPORTS // + +module.exports = invalid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/array/complex64/_package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/array/complex64/_package.json new file mode 100644 index 000000000000..623ec5dbca91 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/array/complex64/_package.json @@ -0,0 +1,59 @@ +{ + "name": "@stdlib/array/complex64", + "version": "0.0.0", + "description": "64-bit complex number array.", + "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" + } + ], + "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" + }, + "main": "./lib", + "directories": { + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "keywords": [ + "stdlib", + "stdtypes", + "types", + "data", + "structure", + "array", + "typed", + "typed array", + "typed-array", + "complex64", + "complex", + "cmplx", + "float32", + "single", + "single-precision", + "float", + "floating", + "floating-point" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/array/complex64/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/array/complex64/lib/index.js new file mode 100644 index 000000000000..8196bcfbd971 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/array/complex64/lib/index.js @@ -0,0 +1,30 @@ +/** +* @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-disable stdlib/jsdoc-main-export */ + +// MODULES // + +var Complex64Array = require( '@stdlib/array/complex64' ); + + +// EXPORTS // + +module.exports = Complex64Array; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/constants/float64/pi/_package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/constants/float64/pi/_package.json new file mode 100644 index 000000000000..f5f2f27785b4 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/constants/float64/pi/_package.json @@ -0,0 +1,52 @@ +{ + "name": "@stdlib/constants/float64/pi", + "version": "0.0.0", + "description": "The mathematical constant pi.", + "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" + } + ], + "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" + }, + "main": "./lib", + "directories": { + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "keywords": [ + "stdlib", + "stdmath", + "constant", + "const", + "mathematics", + "math", + "pi", + "ieee754", + "double", + "dbl", + "float64" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/constants/float64/pi/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/constants/float64/pi/lib/index.js new file mode 100644 index 000000000000..992d23228221 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/constants/float64/pi/lib/index.js @@ -0,0 +1,30 @@ +/** +* @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-disable stdlib/jsdoc-main-export */ + +// MODULES // + +var PI = require( '@stdlib/constants/float64/pi' ); + + +// EXPORTS // + +module.exports = PI; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/abs/_package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/abs/_package.json new file mode 100644 index 000000000000..e0964a5d4a15 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/abs/_package.json @@ -0,0 +1,51 @@ +{ + "name": "@stdlib/math/base/special/abs", + "version": "0.0.0", + "description": "Compute the absolute value of a double-precision floating-point number.", + "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" + } + ], + "main": "./lib", + "directories": { + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "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", + "stdmath", + "mathematics", + "math", + "math.abs", + "abs", + "absolute", + "value", + "magnitude", + "number" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/abs/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/abs/lib/index.js new file mode 100644 index 000000000000..75e38321bd6c --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/abs/lib/index.js @@ -0,0 +1,30 @@ +/** +* @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-disable stdlib/jsdoc-main-export */ + +// MODULES // + +var abs = require( '@stdlib/math/base/special/abs' ); + + +// EXPORTS // + +module.exports = abs; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/pow/_package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/pow/_package.json new file mode 100644 index 000000000000..165b914260c3 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/pow/_package.json @@ -0,0 +1,188 @@ +{ + "name": "@stdlib/math/base/special/pow", + "version": "0.0.0", + "description": "Exponential function.", + "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" + } + ], + "main": "./lib", + "gypfile": true, + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "include": "./include", + "lib": "./lib", + "scripts": "./scripts", + "src": "./src", + "test": "./test" + }, + "types": "./docs/types", + "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", + "stdmath", + "mathematics", + "math", + "math.pow", + "pow", + "power", + "natural", + "exponential", + "function", + "number" + ], + "__stdlib__": { + "scaffold": { + "$schema": "math/base@v1.0", + "base_alias": "pow", + "alias": "pow", + "pkg_desc": "exponential function", + "desc": "exponential function", + "short_desc": "exponential function", + "parameters": [ + { + "name": "x", + "desc": "base", + "type": { + "javascript": "number", + "jsdoc": "number", + "c": "double", + "dtype": "float64" + }, + "domain": [ + { + "min": "-infinity", + "max": "infinity" + } + ], + "rand": { + "prng": "random/base/uniform", + "parameters": [ + -10, + 10 + ] + }, + "example_values": [ + -1.2, + 2, + -3.1, + 4, + 5.5, + 100, + 8.9, + 3.141592653589793, + 11.3, + -3.141592653589793, + 13.5, + 14.6, + -15.7, + 16.8, + -17.9, + 10, + -19.11, + 20.12, + -21.15, + 1 + ] + }, + { + "name": "y", + "desc": "exponent", + "type": { + "javascript": "number", + "jsdoc": "number", + "c": "double", + "dtype": "float64" + }, + "domain": [ + { + "min": "-infinity", + "max": "infinity" + } + ], + "rand": { + "prng": "random/base/uniform", + "parameters": [ + -10, + 10 + ] + }, + "example_values": [ + 1.2, + -2, + 3, + -0.5, + 0, + -5.6, + 8.9, + -10, + 1.5, + -12, + 13.5, + 14.6, + -15.7, + 6, + -17, + 18, + -9, + 2.12, + -1.15, + -2 + ] + } + ], + "returns": { + "desc": "function value", + "type": { + "javascript": "number", + "jsdoc": "number", + "c": "double", + "dtype": "float64" + } + }, + "keywords": [ + "natural", + "exponential", + "pow", + "power" + ], + "extra_keywords": [ + "math.pow" + ] + } + } +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/pow/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/pow/lib/index.js new file mode 100644 index 000000000000..cc9321a7408d --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/pow/lib/index.js @@ -0,0 +1,30 @@ +/** +* @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-disable stdlib/jsdoc-main-export */ + +// MODULES // + +var pow = require( '@stdlib/math/base/special/pow' ); + + +// EXPORTS // + +module.exports = pow; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/sqrt/_package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/sqrt/_package.json new file mode 100644 index 000000000000..0e4f6a30a6cc --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/sqrt/_package.json @@ -0,0 +1,51 @@ +{ + "name": "@stdlib/math/base/special/sqrt", + "version": "0.0.0", + "description": "Compute the principal square root of a double-precision floating-point number.", + "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" + } + ], + "main": "./lib", + "directories": { + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "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", + "stdmath", + "mathematics", + "math", + "math.sqrt", + "sqrt", + "square", + "root", + "principal", + "number" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/sqrt/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/sqrt/lib/index.js new file mode 100644 index 000000000000..2913421bfede --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/math/base/special/sqrt/lib/index.js @@ -0,0 +1,30 @@ +/** +* @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-disable stdlib/jsdoc-main-export */ + +// MODULES // + +var sqrt = require( '@stdlib/math/base/special/sqrt' ); + + +// EXPORTS // + +module.exports = sqrt; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/numel/_package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/numel/_package.json new file mode 100644 index 000000000000..beb30ba97eba --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/numel/_package.json @@ -0,0 +1,51 @@ +{ + "name": "@stdlib/ndarray/numel", + "version": "0.0.0", + "description": "Return the number of elements in an ndarray.", + "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" + } + ], + "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" + }, + "main": "./lib", + "directories": { + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "keywords": [ + "stdlib", + "stdtypes", + "types", + "data", + "structure", + "vector", + "ndarray", + "numel", + "elements", + "length" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/numel/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/numel/lib/index.js new file mode 100644 index 000000000000..680e11ab655c --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/numel/lib/index.js @@ -0,0 +1,30 @@ +/** +* @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-disable stdlib/jsdoc-main-export */ + +// MODULES // + +var numel = require( '@stdlib/ndarray/numel' ); + + +// EXPORTS // + +module.exports = numel; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/vector/int32/_package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/vector/int32/_package.json new file mode 100644 index 000000000000..ba7544b277fc --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/vector/int32/_package.json @@ -0,0 +1,49 @@ +{ + "name": "@stdlib/ndarray/vector/int32", + "version": "0.0.0", + "description": "Create an ndarray vector constructor.", + "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" + } + ], + "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" + }, + "main": "./lib", + "directories": { + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "keywords": [ + "stdlib", + "stdtypes", + "types", + "data", + "structure", + "vector", + "ndarray", + "int32" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/vector/int32/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/vector/int32/lib/index.js new file mode 100644 index 000000000000..3d88c78485d3 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/ndarray/vector/int32/lib/index.js @@ -0,0 +1,29 @@ +/** +* @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-disable stdlib/jsdoc-main-export */ + +// MODULES // + +var Int32Vector = require( '@stdlib/ndarray/vector/int32' ); + +// EXPORTS //` + +module.exports = Int32Vector; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/string/format/_package.json b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/string/format/_package.json new file mode 100644 index 000000000000..d4ea988c1f40 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/string/format/_package.json @@ -0,0 +1,53 @@ +{ + "name": "@stdlib/string/format", + "version": "0.0.0", + "description": "Insert provided variable values into a format string.", + "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" + } + ], + "main": "./lib", + "directories": { + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "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", + "stdstring", + "utilities", + "utility", + "utils", + "util", + "string", + "str", + "format", + "fmt", + "sprintf", + "template" + ] +} diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/string/format/lib/index.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/string/format/lib/index.js new file mode 100644 index 000000000000..a795b3385c3f --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/packages/@stdlib/string/format/lib/index.js @@ -0,0 +1,30 @@ +/** +* @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-disable stdlib/jsdoc-main-export */ + +// MODULES // + +var format = require( '@stdlib/string/format' ); + + +// EXPORTS // + +module.exports = format; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/unvalidated.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/unvalidated.js new file mode 100644 index 000000000000..e07efcbc85c3 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/unvalidated.js @@ -0,0 +1,68 @@ +/** +* @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 unvalidated = []; +var test; + +// Test files without examples or non-TypeScript files +test = { + 'code': [ + '/**', + '* Not a TypeScript declaration file.', + '*', + '* @example', + '* var result = test();', + '* // returns true', + '*/', + 'function test() {', + ' return true;', + '}', + '', + 'module.exports = test;' + ].join( '\n' ), + 'filename': 'test.js' +}; +unvalidated.push( test ); + +test = { + 'code': [ + '/**', + '* Regular TypeScript file (not .d.ts).', + '*', + '* @example', + '* const result = test();', + '* // returns true', + '*/', + 'function test(): boolean {', + ' return true;', + '}', + '', + 'export default test;' + ].join( '\n' ), + 'filename': 'test.ts' +}; +unvalidated.push( test ); + + +// EXPORTS // + +module.exports = unvalidated; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/valid.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/valid.js new file mode 100644 index 000000000000..834904f315eb --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/fixtures/valid.js @@ -0,0 +1,191 @@ +/** +* @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 join = require( 'path' ).join; + + +// VARIABLES // + +var valid = []; +var test; + + +// TESTS // + +test = { + 'code': [ + '/**', + '* Returns the absolute value.', + '*', + '* @param x - input value', + '* @returns absolute value', + '*', + '* @example', + '* var v = abs( -1.0 );', + '* // returns 1.0', + '*/', + 'declare function abs( x: number ): number;', + '', + 'export = abs;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/math/base/special/abs/docs/types/index.d.ts' ) +}; +valid.push( test ); + +test = { + 'code': [ + '/**', + '* Returns the square root.', + '*', + '* @param x - input value', + '* @returns square root', + '*', + '* @example', + '* var v = sqrt( 4.0 );', + '* // returns 2.0', + '*', + '* @example', + '* var v = sqrt( 9.0 );', + '* // returns 3', + '*/', + 'declare function sqrt( x: number ): number;', + '', + 'export = sqrt;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/math/base/special/sqrt/docs/types/index.d.ts' ) +}; +valid.push( test ); + +test = { + 'code': [ + '/**', + '* The mathematical constant pi.', + '*', + '* @example', + '* var pi = PI;', + '* // returns ~3.142', + '*/', + 'declare const PI: number;', + '', + 'export = PI;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/constants/float64/pi/docs/types/index.d.ts' ) +}; +valid.push( test ); + +test = { + 'code': [ + '/**', + '* Complex number array constructor.', + '*', + '* @example', + '* var arr = new Complex64Array();', + '* // returns ', + '*', + '* var len = arr.length;', + '* // returns 0', + '*/', + 'declare class Complex64Array {', + ' constructor();', + ' readonly length: number;', + '}', + '', + 'declare var Complex64Array: {', + ' new(): Complex64Array;', + '};', + '', + 'export = Complex64Array;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/array/complex64/docs/types/index.d.ts' ) +}; +valid.push( test ); + +test = { + 'code': [ + '/**', + '* Console log example.', + '*', + '* @param msg - message to log', + '*', + '* @example', + '* console.log( format( "Hello %s", "World" ) );', + '* // => \'Hello World\'', + '*/', + 'declare function format( template: string, ...args: any[] ): string;', + '', + 'export = format;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/string/format/docs/types/index.d.ts' ) +}; +valid.push( test ); + +test = { + 'code': [ + '/**', + '* Abbreviated Int32Vector example.', + '*', + '* @example', + "* var numel = require( '@stdlib/ndarray/numel' );", + '*', + '* var arr = new Int32Vector();', + '* // returns ', + '*', + '* var len = numel( arr );', + '* // returns 0', + '*/', + 'declare var ctor: Int32Vector;', + '', + 'export = ctor;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/ndarray/vector/int32/docs/types/index.d.ts' ) +}; +valid.push( test ); + +test = { + 'code': [ + '/**', + '* Evaluates the exponential function.', + '*', + '* @param b - base', + '* @param x - exponent', + '* @returns function value', + '*', + '* @example', + '* console.log( pow( 3.0, 2.0 ) );', + '* // => 9.0', + '*', + '* @example', + '* console.log( pow( 2.0, 2.0 ) );', + '* // => 4.0', + '*/', + 'declare function pow( b: number, x: number ): number;', + '', + 'export = pow;' + ].join( '\n' ), + 'filename': join( __dirname, 'packages/@stdlib/math/base/special/pow/docs/types/index.d.ts' ) +}; +valid.push( test ); + + +// EXPORTS // + +module.exports = valid; diff --git a/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/test.js b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/test.js new file mode 100644 index 000000000000..c06ff39a3c79 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/eslint/rules/tsdoc-declarations-doctest/test/test.js @@ -0,0 +1,119 @@ +/** +* @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 proxyquire = require( 'proxyquire' ); +var RuleTester = require( 'eslint' ).RuleTester; +var resolveParentPath = require( '@stdlib/fs/resolve-parent-path' ); + +// Mock the rule to work with renamed _package.json files: +var rule = proxyquire( './../lib/main.js', { + '@stdlib/fs/resolve-parent-path': { + 'sync': function mockResolveParentPath( target, opts ) { + // If looking for package.json, search for _package.json instead: + if ( target === 'package.json' ) { + target = '_package.json'; + } + // Use the original function with the modified target: + return resolveParentPath.sync( target, opts ); + } + } +}); + + +// 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 function positively validates code where all return annotations inside of example code match the actual output', function test( t ) { + var tester = new RuleTester({ + 'parser': require.resolve( '@typescript-eslint/parser' ), + 'parserOptions': { + 'ecmaVersion': 2018, + 'sourceType': 'module' + } + }); + + try { + tester.run( 'tsdoc-declarations-doctest', 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 where not all return annotations inside of example code match the actual output', function test( t ) { + var tester = new RuleTester({ + 'parser': require.resolve( '@typescript-eslint/parser' ), + 'parserOptions': { + 'ecmaVersion': 2018, + 'sourceType': 'module' + } + }); + + try { + tester.run( 'tsdoc-declarations-doctest', rule, { + 'valid': [], + 'invalid': invalid + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +}); + +tape( 'the function does not validate comments without TSDoc examples', function test( t ) { + var tester = new RuleTester({ + 'parser': require.resolve( '@typescript-eslint/parser' ), + 'parserOptions': { + 'ecmaVersion': 2018, + 'sourceType': 'module' + } + }); + + try { + tester.run( 'tsdoc-declarations-doctest', rule, { + 'valid': unvalidated, + 'invalid': [] + }); + t.pass( 'passed without errors' ); + } catch ( err ) { + t.fail( 'encountered an error: ' + err.message ); + } + t.end(); +});