Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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 @@ -22,6 +22,7 @@

var isCapitalized = require( '@stdlib/assert/is-capitalized' );
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
var uppercase = require( '@stdlib/string/base/uppercase' );
var ltrim = require( '@stdlib/string/left-trim' );
var copy = require( '@stdlib/utils/copy' );
var DEFAULTS = require( './defaults.json' );
Expand Down Expand Up @@ -57,7 +58,7 @@ function main( context ) {
if ( hasOwnProp( options, 'whitelist' ) ) {
opts.whitelist = options.whitelist.slice();
}
source = context.getSourceCode();
source = context.sourceCode;
visited = {};

/**
Expand Down Expand Up @@ -89,7 +90,7 @@ function main( context ) {

str = source.getText( comment );
idx = str.search( /[a-zA-Z]/ );
ch = str.charAt( idx ).toUpperCase();
ch = uppercase( str.charAt( idx ) );
replacement = str.slice( 0, idx ) + ch + str.slice( idx+1 );
return fixer.replaceText( comment, replacement );
}
Expand Down Expand Up @@ -194,7 +195,7 @@ function main( context ) {
var i;

comments = source.getCommentsInside( node );
scope = context.getScope( node );
scope = source.getScope( node );
for ( i = 0; i < comments.length; i++ ) {
comment = comments[ i ];
if ( comment.type !== 'Shebang' && !visited[ comment.range ] ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ var rule;
* @returns {Object} validators
*/
function main( context ) {
var source = context.getSourceCode();
var source = context.sourceCode;

/**
* Reports the error message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@

'use strict';

// MODULES //

var walk = require( 'acorn-walk' );


// VARIABLES //

var RE_ANNOTATION = /^\s*(?:\* ){0,1}(?:\/\/|\/\*)* *(?:e\.g\.,){0,1} (returns|=>|throws)/;
Expand All @@ -31,14 +26,103 @@ var rule;

// FUNCTIONS //

/**
* Finds the nearest statement-level ancestor of a given AST node.
*
* @private
* @param {ASTNode} node - AST node
* @returns {ASTNode} statement-level ancestor
*/
function findStatement( node ) {
while ( node ) {
if (
node.type === 'VariableDeclaration' ||
node.type === 'ExpressionStatement' ||
node.type === 'ReturnStatement' ||
node.type === 'ThrowStatement' ||
node.type === 'IfStatement' ||
node.type === 'ForStatement' ||
node.type === 'WhileStatement' ||
node.type === 'TryStatement' ||
node.type === 'FunctionDeclaration' ||
node.type === 'Program'
) {
return node;
}
node = node.parent;
}
return null;
}

/**
* Checks whether a comment is a return annotation and, if so, whether it follows marker style conventions.
*
* @private
* @param {Object} source - source code object
* @param {string} comment - comment to examine
* @returns {(string|null)} error message or null
*/
function checkComment( source, comment ) {
var matches;
var token;
var node;
var type;

matches = comment.value.match( RE_ANNOTATION );
if ( matches ) {
type = matches[ 1 ];

// Find the preceding code token:
token = source.getTokenBefore( comment );
if ( !token ) {
return 'Encountered an orphaned return annotation without a preceding node';
}

// Check for orphaned annotation (preceding token is not on the same or previous line):
if ( comment.loc.start.line - token.loc.end.line > 1 ) {
return 'Encountered an orphaned return annotation without a preceding node';
}

node = source.getNodeByRangeIndex( token.range[ 0 ] );
if ( !node || node.type === 'Program' ) {
return 'Encountered an orphaned return annotation without a preceding node';
}
node = findStatement( node );
if ( !node || node.type === 'Program' ) {
return null;
}
switch ( type ) {
case 'returns':
if (
node.type !== 'VariableDeclaration' &&
( node.type !== 'ExpressionStatement' || node.expression.type !== 'AssignmentExpression' )
) {
return 'Only include `// returns` after variable declarations or assignment expressions (use `=>` after `console.log`)';
}
break;
case '=>':
if (
node.type === 'VariableDeclaration' ||
( node.type === 'ExpressionStatement' && node.expression === 'AssignmentExpression' )
) {
return 'Use `// returns` after variable declarations or assignment expressions instead of `=>`';
}
break;
default:
break;
}
}
return null;
}

/**
* Rule for validating that return annotations follow marker style conventions.
*
* @param {Object} context - ESLint context
* @returns {Object} validators
*/
function main( context ) {
var source = context.getSourceCode();
var source = context.sourceCode;

/**
* Reports the error message.
Expand All @@ -64,85 +148,17 @@ function main( context ) {
function validate( node ) {
var comments;
var current;
var offset;
var prev;
var msg;
var i;

comments = source.getAllComments( node );
if ( comments.length > 0 ) {
current = comments[ 0 ];
msg = checkComment( current, node, 0 );
for ( i = 0; i < comments.length; i++ ) {
current = comments[ i ];
msg = checkComment( source, current );
if ( msg ) {
report( current.loc, msg );
}
for ( i = 1; i < comments.length; i++ ) {
prev = comments[ i-1 ];
current = comments[ i ];
offset = 0;

// Check whether previous comment sits one line before the current one; if so, adjust offset for finding last node:
if ( current.loc.start.line === prev.loc.end.line + 1 ) {
offset = prev.loc.end.column - prev.loc.start.column + 1;
}
msg = checkComment( current, node, offset );
if ( msg ) {
report( current.loc, msg );
}
}
}
}

/**
* Checks whether a comment is a return annotation and, if so, whether it follows marker style conventions.
*
* @private
* @param {string} comment - comment to examine
* @param {ASTNode} ast - node to examine
* @param {integer} offset - non-zero if previous line ends with a comment
* @returns {(string|null)} error message or null
*/
function checkComment( comment, ast, offset ) {
var matches;
var node;
var prev;
var type;

matches = comment.value.match( RE_ANNOTATION );
if ( matches ) {
offset += 1 + comment.loc.start.column;
prev = walk.findNodeAt( ast, null, comment.start-offset );
type = matches[ 1 ];
if ( !prev ) {
// Handle case when comment refers to node on the same line:
if ( walk.findNodeAt( ast, null, comment.start-1 ) ) {
return null;
}
return 'Encountered an orphaned return annotation without a preceding node';
}
node = prev.node;
switch ( type ) {
case 'returns':
if (
node.type !== 'VariableDeclaration' &&
( node.type !== 'ExpressionStatement' || node.expression.type !== 'AssignmentExpression' )
) {
return 'Only include `// returns` after variable declarations or assignment expressions (use `=>` after `console.log`)';
}
break;
case '=>':
if (
node.type === 'VariableDeclaration' ||
( node.type === 'ExpressionStatement' && node.expression === 'AssignmentExpression' )
) {
return 'Use `// returns` after variable declarations or assignment expressions instead of `=>`';
}
break;
default:
break;
}
}
return null;
}

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ test = {
'code': [
'var functionName = require( \'./../lib\' );',
'',
'console.log( functionName( Math.sqrt ) ); // eslint-disable-line stdlib/no-builtin-math',
'console.log( functionName( Math.sqrt ) );',
'// => \'sqrt\'',
'',
'console.log( functionName( Float64Array ) );',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ function checkComment( comment ) {
* @returns {Object} validators
*/
function main( context ) {
var source = context.getSourceCode();
var source = context.sourceCode;

/**
* Reports the error message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ function main( context ) {
var scope;
var dir;

source = context.getSourceCode();
source = context.sourceCode;
if ( NODE_SHEBANG.test( source.text ) ) {
// Do not lint executable Node.js script files:
return {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var rule;
* @returns {Object} validators
*/
function main( context ) {
var source = context.getSourceCode();
var source = context.sourceCode;

/**
* Reports the error message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var rule;
* @returns {Object} validators
*/
function main( context ) {
var source = context.getSourceCode();
var source = context.sourceCode;

/**
* Reports the error message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,26 @@ var rule;

// FUNCTIONS //

/**
* Creates a location object.
*
* @private
* @param {Object} options - function options
* @returns {Object} location info
*/
function locationInfo( options ) {
return {
'start': {
'line': options.startLine,
'column': options.startColumn
},
'end': {
'line': options.endLine,
'column': options.endColumn
}
};
}

/**
* Rule for enforcing Markdown blockquote indentation in JSDoc descriptions.
*
Expand All @@ -63,7 +83,7 @@ function main( context ) {
]
};
lint = remark().use( config ).processSync; // eslint-disable-line node/no-sync
source = context.getSourceCode();
source = context.sourceCode;

return {
'FunctionExpression:exit': validate,
Expand Down Expand Up @@ -121,26 +141,6 @@ function main( context ) {
}
}

/**
* Creates a location object.
*
* @private
* @param {Object} options - function options
* @returns {Object} location info
*/
function locationInfo( options ) {
return {
'start': {
'line': options.startLine,
'column': options.startColumn
},
'end': {
'line': options.endLine,
'column': options.endColumn
}
};
}

/**
* Reports an error message.
*
Expand Down
Loading