Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,21 @@ function main( context ) {
}
}

/**
* Sorts `require` statements based on their ranks.
*
* @private
* @param {Object} a - first require statement
* @param {Object} b - second require statement
* @returns {number} number indicating sort order
*/
function sortRequires( a, b ) {
if ( a.rank < b.rank ) {
return -1;
}
return 1;
}

/**
* Reports the error message.
*
Expand All @@ -141,9 +156,65 @@ function main( context ) {
context.report({
'node': null,
'message': msg,
'loc': curr.node.loc
'loc': curr.node.loc,
'fix': fix
});
}

/**
* Fixes the lint error by reordering the require statements.
*
* @private
* @param {Function} fixer - ESLint fixer
* @returns {(Object|Null)} fix or null
*/
function fix(fixer) {
var requireDeclarations;
var replacingText;
var startRange;
var endRange;
var source;
var elem;
var txt;
var i;

replacingText = '';
requireDeclarations = [];
source = context.getSourceCode();

// Get the text and rank for the require statements:
for ( i = 0; i < requires.length; i++ ) {
elem = requires[i].node.parent.parent;
txt = source.getText(elem);
if ( i === 0 ) {
startRange = elem.range[ 0 ] - elem.loc.start.column;
}
endRange = elem.range[ 1 ];
requireDeclarations.push( {
'text': txt,
'rank': requires[i].rank
});
}

// Sort the require statements:
requireDeclarations.sort( sortRequires );

// Build the replacement text:
for ( i = 0; i < requireDeclarations.length; i++ ) {
txt = requireDeclarations[ i ].text;
if ( !txt.startsWith( 'var' ) ) {
txt = 'var '+txt;
}
if ( !txt.endsWith( ';' ) ) {
txt += ';';
}
replacingText += txt;
Copy link
Member Author

@headlessNode headlessNode Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kgryte @Planeshifter The var starting and ; ending code here is because of how ESLint AST Node differs in case of chained calls and IIFE's.

In those cases, the source.getText function misses the var keyword and the ending semi-colon. See: https://github.com/stdlib-js/stdlib/pull/3323/files#diff-e79d1dfb379d74e202651a48d6e3b925d041ece9221da5ce5fef6dce0f9f49e1R128

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Thanks for explaining @headlessNode.

if ( i < requireDeclarations.length-1 ) {
replacingText += '\n';
}
}
return fixer.replaceTextRange( [ startRange, endRange ], replacingText );// eslint-disable-line max-len
}
}

/**
Expand Down Expand Up @@ -196,9 +267,11 @@ function main( context ) {

rule = {
'meta': {
'type': 'layout',
'docs': {
'description': 'enforce that `require()` calls follow a specified order'
},
'fixable': 'code',
'schema': [
{
'type': 'object',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ test = {
{
'message': '`require( \'fs\' )` should come before `require( \'@stdlib/math/base/special/betainc\' )`'
}
]
],
'output': [
'// MODULES //',
'',
'var fs = require( \'fs\' );',
'var betainc = require( \'@stdlib/math/base/special/betainc\' );'
].join( '\n' )
};
invalid.push( test );

Expand All @@ -47,7 +53,13 @@ test = {
{
'message': '`require( \'fs\' )` should come before `require( \'debug\' )`'
}
]
],
'output': [
'// MODULES //',
'',
'var fs = require( \'fs\' );',
'var debug = require( \'debug\' );'
].join( '\n' )
};
invalid.push( test );

Expand All @@ -62,7 +74,13 @@ test = {
{
'message': '`require( \'debug\' )` should come before `require( \'./validate.js\' )`'
}
]
],
'output': [
'// MODULES //',
'',
'var debug = require( \'debug\' );',
'var validate = require( \'./validate.js\' );'
].join( '\n' )
};
invalid.push( test );

Expand All @@ -80,7 +98,13 @@ test = {
{
'message': '`require( \'debug\' )` should come before `require( \'./validate.js\' )`'
}
]
],
'output': [
'// MODULES //',
'',
'var debug = require( \'debug\' );',
'var validate = require( \'./validate.js\' );'
].join( '\n' )
};
invalid.push( test );

Expand All @@ -100,7 +124,18 @@ test = {
{
'message': '`require( \'path\' )` should come before `require( \'debug\' )`'
}
]
],
'output': [
'var resolve = require( \'path\' ).resolve;',
'var debug = require( \'debug\' )( \'links:create:sync\' );',
'var instanceOf = require( \'@stdlib/assert/instance-of\' );',
'var readJSON = require( \'@stdlib/fs/read-json\' ).sync;',
'var writeFile = require( \'@stdlib/fs/write-file\' ).sync;',
'var cwd = require( \'@stdlib/process/cwd\' );',
'var config = require( \'./defaults.js\' );',
'var validate = require( \'./validate.js\' );',
'var insert = require( \'./insert.js\' );'
].join( '\n' )
};
invalid.push( test );

Expand All @@ -122,7 +157,14 @@ test = {
{
'message': '`require( \'fs\' )` should come before `require( \'@stdlib/math\' )`'
}
]
],
'output': [
'// MODULES //',
'',
'var fs = require( \'fs\' );',
'var debug = require( \'debug\' );',
'var math = require( \'@stdlib/math\' );'
].join( '\n' )
};
invalid.push( test );

Expand All @@ -141,7 +183,14 @@ test = {
{
'message': '`require( \'tape\' )` should come before `require( \'@stdlib/math/base/special/abs\' )`'
}
]
],
'output': [
'// MODULES //',
'',
'var tape = require( \'tape\' );',
'var abs = require( \'@stdlib/math/base/special/abs\' );',
'var main = require( \'./../lib/index.js\' );'
].join( '\n' )
};
invalid.push( test );

Expand Down
Loading