Skip to content

Commit

Permalink
feat: add fixer function
Browse files Browse the repository at this point in the history
  • Loading branch information
headlessNode committed Dec 6, 2024
1 parent 6e86cea commit 8630e60
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,67 +37,159 @@ var OPTS_COMPARE = {
* @returns {Object} validators
*/
function main( context ) {
var expressions;
var prevAlias;
var sorted;

return {
'ObjectExpression': validate
};
expressions = [];

/**
* Checks whether packages are added to a REPL namespace object in alphabetical order according to alias (namespace key).
* Extracts the alias value from a given node.
*
* @private
* @param {ASTNode} node - node to examine
* @param {ASTNode} node - node containing properties to search
* @returns {string} alias value
*/
function validate( node ) {
var properties;
function getAlias( node ) {
var props;
var alias;
var prop;
var i;

properties = node.properties;
for ( i = 0; i < properties.length; i++ ) {
prop = properties[ i ];
if ( prop.key.value === 'alias' ) {
alias = prop.value.value;
props = node.properties;
for ( i = 0; i < props.length; i++ ) {
if ( props[ i ].key.value === 'alias' ) {
alias = props[ i ].value.value;
if ( alias ) {
if (
prevAlias &&
alias.localeCompare( prevAlias, 'en', OPTS_COMPARE ) < 0 )
{
report( prevAlias, alias, node );
} else {
prevAlias = alias;
}
return alias;
}
}
}
}

/**
* Compares two nodes and determines their order based on the alias property.
*
* @private
* @param {ASTNode} a - first node
* @param {ASTNode} b - second node
* @returns {number} number indicating sort order
*/
function sortExpressions( a, b ) {
var aliasA = getAlias( a.arguments[ 0 ] );
var aliasB = getAlias( b.arguments[ 0 ] );
return aliasA.localeCompare( aliasB, 'en', OPTS_COMPARE );
}

/**
* Reports the error message.
*
* @private
* @param {string} last - name of first package
* @param {string} current - name of second package
* @param {string} current - name of first package
* @param {string} last - name of second package
* @param {ASTNode} node - node to report
*/
function report( last, current, node ) {
function report( current, last, node ) {
context.report({
'node': node,
'message': '"'+current+'" should come before "'+last+'"'
'message': '"'+last+'" should come before "'+current+'"',
'fix': fix
});

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

source = context.getSourceCode();
replacingText = '';
startRange = expressions[0].range[ 0 ];
endRange = expressions[ expressions.length - 1 ].range[ 1 ];

sorted = expressions.slice().sort( sortExpressions );

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

/**
* Checks whether the packages are added to REPL namespace object in alphabetical order according to alias (namespace key).
*
* @private
*/
function validate( ) {
var alias;
var i;

for ( i = 0; i < expressions.length; i++ ) {
alias = getAlias( expressions[ i ].arguments[ 0 ] );
if (
prevAlias &&
alias.localeCompare( prevAlias, 'en', OPTS_COMPARE ) < 0
) {
report( prevAlias, alias, expressions[ i ].arguments[ 0 ] );
} else {
prevAlias = alias;
}
}
}

/**
* Collects all expressions which add a package to REPL namespace.
*
* @private
* @param {ASTNode} node - node to examine
*/
function collectExpressions( node ) {
var object;
var alias;

if (
node.callee.type === 'MemberExpression' &&
node.callee.object.name === 'ns' &&
node.callee.property.name === 'push'
) {
object = node.arguments[ 0 ];
if ( object.type === 'ObjectExpression' ) {
alias = getAlias( object );
if ( alias ) {
expressions.push( node );
}
}
}
}

return {
'CallExpression': collectExpressions,
'Program:exit': validate
};
}


// MAIN //

rule = {
'meta': {
'type': 'layout',
'docs': {
'description': 'enforce that packages are added to a REPL namespace object in alphabetical order according to alias (namespace key)'
},
'fixable': 'code',
'schema': []
},
'create': main
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,67 @@ test = {
'message': '"hasInt8ArraySupport" should come before "hasMapSupport"',
'type': 'ObjectExpression'
}
]
],
'output': [
'ns.push({',
' \'alias\': \'hasInt8ArraySupport\',',
' \'path\': \'@stdlib/assert/has-int8array-support\',',
' \'value\': require( \'@stdlib/assert/has-int8array-support\' ),',
' \'type\': \'Function\',',
' \'related\': []',
'});',
'',
'ns.push({',
' \'alias\': \'hasInt32ArraySupport\',',
' \'path\': \'@stdlib/assert/has-int32array-support\',',
' \'value\': require( \'@stdlib/assert/has-int32array-support\' ),',
' \'type\': \'Function\',',
' \'related\': []',
'});',
'',
'ns.push({',
' \'alias\': \'hasMapSupport\',',
' \'path\': \'@stdlib/assert/has-map-support\',',
' \'value\': require( \'@stdlib/assert/has-map-support\' ),',
' \'type\': \'Function\',',
' \'related\': []',
'});'
].join( '\n' )
};
invalid.push( test );

test = {
'code': [
'ns.push({',
' \'alias\': \'pop\',',
' \'path\': \'@stdlib/utils/pop\',',
' \'value\': require( \'@stdlib/utils/pop\' ),',
' \'type\': \'Function\',',
' \'related\': [',
' \'@stdlib/utils/push\',',
' \'@stdlib/utils/shift\',',
' \'@stdlib/utils/unshift\'',
' ]',
'});',
'',
'ns.push({',
' \'alias\': \'pluck\',',
' \'path\': \'@stdlib/utils/pluck\',',
' \'value\': require( \'@stdlib/utils/pluck\' ),',
' \'type\': \'Function\',',
' \'related\': [',
' \'@stdlib/utils/deep-pluck\',',
' \'@stdlib/utils/pick\'',
' ]',
'});'
].join( '\n' ),
'errors': [
{
'message': '"pluck" should come before "pop"',
'type': 'ObjectExpression'
}
],
'output': [
'ns.push({',
' \'alias\': \'pluck\',',
' \'path\': \'@stdlib/utils/pluck\',',
Expand All @@ -86,14 +141,9 @@ test = {
' \'@stdlib/utils/unshift\'',
' ]',
'});'
].join( '\n' ),
'errors': [
{
'message': '"hasInt32ArraySupport" should come before "hasMapSupport"',
'type': 'ObjectExpression'
}
]
].join( '\n' )
};
invalid.push( test );

test = {
'code': [
Expand Down Expand Up @@ -122,7 +172,28 @@ test = {
'message': '"AFINN_96" should come before "AFINN_111"',
'type': 'ObjectExpression'
}
]
],
'output': [
'ns.push({',
' \'alias\': \'AFINN_96\',',
' \'path\': \'@stdlib/datasets/afinn-96\',',
' \'value\': require( \'@stdlib/datasets/afinn-96\' ),',
' \'type\': \'Function\',',
' \'related\': [',
' \'@stdlib/datasets/afinn-111\'',
' ]',
'});',
'',
'ns.push({',
' \'alias\': \'AFINN_111\',',
' \'path\': \'@stdlib/datasets/afinn-111\',',
' \'value\': require( \'@stdlib/datasets/afinn-111\' ),',
' \'type\': \'Function\',',
' \'related\': [',
' \'@stdlib/datasets/afinn-96\'',
' ]',
'});'
].join( '\n' )
};
invalid.push( test );

Expand Down

0 comments on commit 8630e60

Please sign in to comment.