94%
lib94%
rules96%
checker.js
var vowFs = require('vow-fs');
var Vow = require('vow');
var StringChecker = require('./string-checker');
var extractJs = require('./extract-js');
var utils = require('util');
var NodeConfiguration = require('./config/node-configuration');
/**
* Starts Code Style checking process.
*
* @name Checker
* @see StringChecker constructor
*/
Function (anonymous_1)
✓ Was called
var Checker = function() {···
StringChecker.apply(this, arguments);
};
var Checker = function() {
StringChecker.apply(this, arguments);
};
utils.inherits(Checker, StringChecker);
/**
* Loads configuration from JS Object. Activates and configures required rules.
*
* @param {Object} config
*/
Function (anonymous_2)
✓ Was called
Checker.prototype.configure = function(config) {···
StringChecker.prototype.configure.call(this, config);
};
Checker.prototype.configure = function(config) {
StringChecker.prototype.configure.call(this, config);
};
/**
* Execute checker depending on config value either checks or checks and fixes
*
* @see Checker#checkPath/Checker#fixPath
*/
Function (anonymous_3)
✓ Was called
Checker.prototype.execute = function() {···
var method = this._configuration.getFix() === true ? this.fixPath : this.checkPath;

return method.apply(this, arguments);
};
Checker.prototype.execute = function() {
Branch ConditionalExpression
✓ Positive was returned (? ...)
var method = this._configuration.getFix() === true ? this.fixPath : this.checkPath;
✓ Negative was returned (: ...)
var method = this._configuration.getFix() === true ? this.fixPath : this.checkPath;
var method = this._configuration.getFix() === true ? this.fixPath : this.checkPath;
return method.apply(this, arguments);
};
/**
* Checks single file.
*
* @param {String} path
* @returns {Promise.<Errors>}
*/
Function (anonymous_4)
✓ Was called
Checker.prototype.checkFile = function(path) {···
if (this._configuration.isFileExcluded(path)) {
return Vow.resolve(null);
}

return vowFs.read(path, 'utf8').then(function(data) {
return this.checkString(data, path);
}, this);
};
Checker.prototype.checkFile = function(path) {
Branch IfStatement
✓ Positive was executed (if)
if (this._configuration.isFileExcluded(path)) {···
return Vow.resolve(null);
}
✓ Negative was executed (else)
}···

return vowFs.read(path, 'utf8').then(function(data) {
if (this._configuration.isFileExcluded(path)) {
return Vow.resolve(null);
}
Function (anonymous_5)
✓ Was called
return vowFs.read(path, 'utf8').then(function(data) {···
return this.checkString(data, path);
}, this);
return vowFs.read(path, 'utf8').then(function(data) {
return this.checkString(data, path);
}, this);
};
/**
* Fixes single file.
*
* @param {String} path
* @returns {Promise.<Errors>}
*/
Function (anonymous_6)
✓ Was called
Checker.prototype.fixFile = function(path) {···
if (this._configuration.isFileExcluded(path)) {
return Vow.resolve(null);
}

return vowFs.read(path, 'utf8').then(function(data) {
var result = this.fixString(data, path);
return vowFs.write(path, result.output).then(function() {
return result.errors;
});
}, this);
};
Checker.prototype.fixFile = function(path) {
Branch IfStatement
✓ Positive was executed (if)
if (this._configuration.isFileExcluded(path)) {···
return Vow.resolve(null);
}
✓ Negative was executed (else)
}···

return vowFs.read(path, 'utf8').then(function(data) {
if (this._configuration.isFileExcluded(path)) {
return Vow.resolve(null);
}
Function (anonymous_7)
✓ Was called
return vowFs.read(path, 'utf8').then(function(data) {···
var result = this.fixString(data, path);
return vowFs.write(path, result.output).then(function() {
return result.errors;
});
}, this);
return vowFs.read(path, 'utf8').then(function(data) {
var result = this.fixString(data, path);
Function (anonymous_8)
✓ Was called
return vowFs.write(path, result.output).then(function() {···
return result.errors;
});
return vowFs.write(path, result.output).then(function() {
return result.errors;
});
}, this);
};
/**
* Extract JavaScript from file.
*
* @param {String} path
* @returns {Promise.<Errors>}
*/
Function (anonymous_9)
✓ Was called
Checker.prototype.extractFile = function(path) {···
if (this._configuration.isFileExcluded(path)) {
return Vow.resolve(null);
}

if (!this._configuration.shouldExtractFile(path)) {
return Vow.resolve(null);
}

return vowFs.read(path, 'utf8').then(function(data) {
var result = extractJs(path, data);

result.sources.forEach(function(script) {
this.checkString(script.source, path).getErrorList().forEach(function(error) {
error.line += script.line;
error.column += script.offset;
result.addError(error);
});
}, this);

return result.errors;
}, this);
};
Checker.prototype.extractFile = function(path) {
Branch IfStatement
✓ Positive was executed (if)
if (this._configuration.isFileExcluded(path)) {···
return Vow.resolve(null);
}
✓ Negative was executed (else)
}···

if (!this._configuration.shouldExtractFile(path)) {
if (this._configuration.isFileExcluded(path)) {
return Vow.resolve(null);
}
Branch IfStatement
✓ Positive was executed (if)
if (!this._configuration.shouldExtractFile(path)) {···
return Vow.resolve(null);
}
✓ Negative was executed (else)
}···

return vowFs.read(path, 'utf8').then(function(data) {
if (!this._configuration.shouldExtractFile(path)) {
return Vow.resolve(null);
}
Function (anonymous_10)
✓ Was called
return vowFs.read(path, 'utf8').then(function(data) {···
var result = extractJs(path, data);

result.sources.forEach(function(script) {
this.checkString(script.source, path).getErrorList().forEach(function(error) {
error.line += script.line;
error.column += script.offset;
result.addError(error);
});
}, this);

return result.errors;
}, this);
return vowFs.read(path, 'utf8').then(function(data) {
var result = extractJs(path, data);
Function (anonymous_11)
✓ Was called
result.sources.forEach(function(script) {···
this.checkString(script.source, path).getErrorList().forEach(function(error) {
error.line += script.line;
error.column += script.offset;
result.addError(error);
});
}, this);
result.sources.forEach(function(script) {
Function (anonymous_12)
✓ Was called
this.checkString(script.source, path).getErrorList().forEach(function(error) {···
error.line += script.line;
error.column += script.offset;
result.addError(error);
});
this.checkString(script.source, path).getErrorList().forEach(function(error) {
error.line += script.line;
error.column += script.offset;
result.addError(error);
});
}, this);
return result.errors;
}, this);
};
/**
* Checks directory recursively.
*
* @param {String} path
* @returns {Promise.<Error[]>}
*/
Function (anonymous_13)
✓ Was called
Checker.prototype.checkDirectory = function(path) {···
return this._processDirectory(path, this.checkFile.bind(this));
};
Checker.prototype.checkDirectory = function(path) {
return this._processDirectory(path, this.checkFile.bind(this));
};
/**
* Checks directory or file.
*
* @param {String} path
* @returns {Promise.<Error[]>}
*/
Function (anonymous_14)
✓ Was called
Checker.prototype.checkPath = function(path) {···
return this._processPath(path, this.checkFile.bind(this));
};
Checker.prototype.checkPath = function(path) {
return this._processPath(path, this.checkFile.bind(this));
};
/**
* Fixes directory or file.
*
* @param {String} path
* @returns {Promise.<Error[]>}
*/
Function (anonymous_15)
✓ Was called
Checker.prototype.fixPath = function(path) {···
return this._processPath(path, this.fixFile.bind(this));
};
Checker.prototype.fixPath = function(path) {
return this._processPath(path, this.fixFile.bind(this));
};
/**
* Processes directory recursively.
*
* @param {String} path
* @param {Function} fileHandler
* @returns {Promise.<Error[]>}
*/
Function (anonymous_16)
✓ Was called
Checker.prototype._processDirectory = function(path, fileHandler) {···
return vowFs.listDir(path).then(function(filenames) {
return Vow.all(filenames.map(function(filename) {
var fullname = path + '/' + filename;

if (this._configuration.isFileExcluded(fullname)) {
return [];
}

return vowFs.stat(fullname).then(function(stat) {
if (stat.isDirectory()) {
return this._processDirectory(fullname, fileHandler);
}

if (!this._configuration.hasCorrectExtension(fullname)) {
if (!this._configuration.shouldExtractFile(fullname)) {
return [];
}

return this.extractFile(fullname);
}

return fileHandler(fullname);
}, this);
}, this)).then(function(results) {
return [].concat.apply([], results);
});
}, this);
};
Checker.prototype._processDirectory = function(path, fileHandler) {
Function (anonymous_17)
✓ Was called
return vowFs.listDir(path).then(function(filenames) {···
return Vow.all(filenames.map(function(filename) {
var fullname = path + '/' + filename;

if (this._configuration.isFileExcluded(fullname)) {
return [];
}

return vowFs.stat(fullname).then(function(stat) {
if (stat.isDirectory()) {
return this._processDirectory(fullname, fileHandler);
}

if (!this._configuration.hasCorrectExtension(fullname)) {
if (!this._configuration.shouldExtractFile(fullname)) {
return [];
}

return this.extractFile(fullname);
}

return fileHandler(fullname);
}, this);
}, this)).then(function(results) {
return [].concat.apply([], results);
});
}, this);
return vowFs.listDir(path).then(function(filenames) {
Function (anonymous_18)
✓ Was called
return Vow.all(filenames.map(function(filename) {···
var fullname = path + '/' + filename;

if (this._configuration.isFileExcluded(fullname)) {
return [];
}

return vowFs.stat(fullname).then(function(stat) {
if (stat.isDirectory()) {
return this._processDirectory(fullname, fileHandler);
}

if (!this._configuration.hasCorrectExtension(fullname)) {
if (!this._configuration.shouldExtractFile(fullname)) {
return [];
}

return this.extractFile(fullname);
}

return fileHandler(fullname);
}, this);
}, this)).then(function(results) {
return Vow.all(filenames.map(function(filename) {
var fullname = path + '/' + filename;
Branch IfStatement
✓ Positive was executed (if)
if (this._configuration.isFileExcluded(fullname)) {···
return [];
}
✓ Negative was executed (else)
}···

return vowFs.stat(fullname).then(function(stat) {
if (this._configuration.isFileExcluded(fullname)) {
return [];
}
Function (anonymous_19)
✓ Was called
return vowFs.stat(fullname).then(function(stat) {···
if (stat.isDirectory()) {
return this._processDirectory(fullname, fileHandler);
}

if (!this._configuration.hasCorrectExtension(fullname)) {
if (!this._configuration.shouldExtractFile(fullname)) {
return [];
}

return this.extractFile(fullname);
}

return fileHandler(fullname);
}, this);
return vowFs.stat(fullname).then(function(stat) {
Branch IfStatement
✓ Positive was executed (if)
if (stat.isDirectory()) {···
return this._processDirectory(fullname, fileHandler);
}
✓ Negative was executed (else)
}···

if (!this._configuration.hasCorrectExtension(fullname)) {
if (stat.isDirectory()) {
return this._processDirectory(fullname, fileHandler);
}
Branch IfStatement
✓ Positive was executed (if)
if (!this._configuration.hasCorrectExtension(fullname)) {···
if (!this._configuration.shouldExtractFile(fullname)) {
return [];
}

return this.extractFile(fullname);
}
✓ Negative was executed (else)
}···

return fileHandler(fullname);
if (!this._configuration.hasCorrectExtension(fullname)) {
Branch IfStatement
✓ Positive was executed (if)
if (!this._configuration.shouldExtractFile(fullname)) {···
return [];
}
✓ Negative was executed (else)
}···

return this.extractFile(fullname);
if (!this._configuration.shouldExtractFile(fullname)) {
return [];
}
return this.extractFile(fullname);
}
return fileHandler(fullname);
}, this);
Function (anonymous_20)
✓ Was called
}, this)).then(function(results) {···
return [].concat.apply([], results);
});
}, this)).then(function(results) {
return [].concat.apply([], results);
});
}, this);
};
/**
* Processes directory or file.
*
* @param {String} path
* @param {Function} fileHandler
* @returns {Promise.<Error[]>}
*/
Function (anonymous_21)
✓ Was called
Checker.prototype._processPath = function(path, fileHandler) {···
path = path.replace(/\/$/, '');

return vowFs.exists(path).then(function(exists) {
if (!exists) {
throw new Error('Path ' + path + ' was not found.');
}

return vowFs.stat(path).then(function(stat) {
if (stat.isDirectory()) {
return this._processDirectory(path, fileHandler);
}

return fileHandler(path).then(function(errors) {
if (errors) {
return [errors];
}

return [];
});
}, this);
}, this);
};
Checker.prototype._processPath = function(path, fileHandler) {
path = path.replace(/\/$/, '');
Function (anonymous_22)
✓ Was called
return vowFs.exists(path).then(function(exists) {···
if (!exists) {
throw new Error('Path ' + path + ' was not found.');
}

return vowFs.stat(path).then(function(stat) {
if (stat.isDirectory()) {
return this._processDirectory(path, fileHandler);
}

return fileHandler(path).then(function(errors) {
if (errors) {
return [errors];
}

return [];
});
}, this);
}, this);
return vowFs.exists(path).then(function(exists) {
Branch IfStatement
✓ Positive was executed (if)
if (!exists) {···
throw new Error('Path ' + path + ' was not found.');
}
✓ Negative was executed (else)
}···

return vowFs.stat(path).then(function(stat) {
if (!exists) {
throw new Error('Path ' + path + ' was not found.');
}
Function (anonymous_23)
✓ Was called
return vowFs.stat(path).then(function(stat) {···
if (stat.isDirectory()) {
return this._processDirectory(path, fileHandler);
}

return fileHandler(path).then(function(errors) {
if (errors) {
return [errors];
}

return [];
});
}, this);
return vowFs.stat(path).then(function(stat) {
Branch IfStatement
✓ Positive was executed (if)
if (stat.isDirectory()) {···
return this._processDirectory(path, fileHandler);
}
✓ Negative was executed (else)
}···

return fileHandler(path).then(function(errors) {
if (stat.isDirectory()) {
return this._processDirectory(path, fileHandler);
}
Function (anonymous_24)
✓ Was called
return fileHandler(path).then(function(errors) {···
if (errors) {
return [errors];
}

return [];
});
return fileHandler(path).then(function(errors) {
Branch IfStatement
✓ Positive was executed (if)
if (errors) {···
return [errors];
}
✓ Negative was executed (else)
}···

return [];
if (errors) {
return [errors];
}
return [];
});
}, this);
}, this);
};
/**
* Checks stdin for input
*
* @returns {Promise}
*/
Function (anonymous_25)
✓ Was called
Checker.prototype.checkStdin = function() {···
return this._processStdin(this.checkString.bind(this));
};
Checker.prototype.checkStdin = function() {
return this._processStdin(this.checkString.bind(this));
};
/**
* Fixes stdin input
*
* @returns {Promise}
*/
Function (anonymous_26)
✓ Was called
Checker.prototype.fixStdin = function() {···
return this._processStdin(this.fixString.bind(this));
};
Checker.prototype.fixStdin = function() {
return this._processStdin(this.fixString.bind(this));
};
/**
*
* @param {Function} stdinHandler
* @returns {Promise}
*/
Function (anonymous_27)
✓ Was called
Checker.prototype._processStdin = function(stdinHandler) {···
var stdInput = [];
var deferred = Vow.defer();

process.stdin.setEncoding('utf8');

process.stdin.on('data', function(chunk) {
stdInput.push(chunk);
});

process.stdin.on('end', function() {
deferred.resolve(stdinHandler(stdInput.join('')));
});

return deferred.promise();
};
Checker.prototype._processStdin = function(stdinHandler) {
var stdInput = [];
var deferred = Vow.defer();
process.stdin.setEncoding('utf8');
Function (anonymous_28)
✓ Was called
process.stdin.on('data', function(chunk) {···
stdInput.push(chunk);
});
process.stdin.on('data', function(chunk) {
stdInput.push(chunk);
});
Function (anonymous_29)
✓ Was called
process.stdin.on('end', function() {···
deferred.resolve(stdinHandler(stdInput.join('')));
});
process.stdin.on('end', function() {
deferred.resolve(stdinHandler(stdInput.join('')));
});
return deferred.promise();
};
/**
* Returns new configuration instance.
*
* @protected
* @returns {NodeConfiguration}
*/
Function (anonymous_30)
✓ Was called
Checker.prototype._createConfiguration = function() {···
return new NodeConfiguration();
};
Checker.prototype._createConfiguration = function() {
return new NodeConfiguration();
};
module.exports = Checker;
string-checker.js
var Errors = require('./errors');
var JsFile = require('./js-file');
var TokenIndex = require('./token-index');
var Configuration = require('./config/configuration');
var MAX_FIX_ATTEMPTS = 5;
Function getInternalErrorMessage
✓ Was called
function getInternalErrorMessage(rule, e) {···
return 'Error running rule ' + rule + ': ' +
'This is an issue with JSCS and not your codebase.\n' +
'Please file an issue (with the stack trace below) at: ' +
'https://github.com/jscs-dev/node-jscs/issues/new\n' + e.stack;
}
function getInternalErrorMessage(rule, e) {
return 'Error running rule ' + rule + ': ' +
'This is an issue with JSCS and not your codebase.\n' +
'Please file an issue (with the stack trace below) at: ' +
'https://github.com/jscs-dev/node-jscs/issues/new\n' + e.stack;
}
/**
* Starts Code Style checking process.
*
* @name StringChecker
*/
Function (anonymous_32)
✓ Was called
var StringChecker = function() {···
this._configuredRules = [];

this._errorsFound = 0;
this._maxErrorsExceeded = false;

this._configuration = this._createConfiguration();
this._configuration.registerDefaultPresets();
};
var StringChecker = function() {
this._configuredRules = [];
this._errorsFound = 0;
this._maxErrorsExceeded = false;
this._configuration = this._createConfiguration();
this._configuration.registerDefaultPresets();
};
StringChecker.prototype = {
/**
* Registers single Code Style checking rule.
*
* @param {Rule} rule
*/
Function (anonymous_33)
✓ Was called
registerRule: function(rule) {···
this._configuration.registerRule(rule);
},
registerRule: function(rule) {
this._configuration.registerRule(rule);
},
/**
* Registers built-in Code Style checking rules.
*/
Function (anonymous_34)
✓ Was called
registerDefaultRules: function() {···
this._configuration.registerDefaultRules();
},
registerDefaultRules: function() {
this._configuration.registerDefaultRules();
},
/**
* Get processed config.
*
* @return {Object}
*/
Function (anonymous_35)
✗ Was not called
getProcessedConfig: function() {···
return this._configuration.getProcessedConfig();
},
getProcessedConfig: function() {
return this._configuration.getProcessedConfig();
},
/**
* Loads configuration from JS Object. Activates and configures required rules.
*
* @param {Object} config
*/
Function (anonymous_36)
✓ Was called
configure: function(config) {···
this._configuration.load(config);

this._configuredRules = this._configuration.getConfiguredRules();
this._maxErrors = this._configuration.getMaxErrors();
},
configure: function(config) {
this._configuration.load(config);
this._configuredRules = this._configuration.getConfiguredRules();
this._maxErrors = this._configuration.getMaxErrors();
},
/**
* Checks file provided with a string.
*
* @param {String} source
* @param {String} [filename='input']
* @returns {Errors}
*/
Function (anonymous_37)
✓ Was called
checkString: function(source, filename) {···
filename = filename || 'input';

var file = this._createJsFileInstance(filename, source);

var errors = new Errors(file);

file.getParseErrors().forEach(function(parseError) {
if (!this._maxErrorsExceeded) {
this._addParseError(errors, parseError, file);
}
}, this);

if (!file._program || file._program.firstChild.type === 'EOF') {
return errors;
}

this._checkJsFile(file, errors);

return errors;
},
checkString: function(source, filename) {
Branch LogicalExpression
✓ Was returned
filename = filename || 'input';
✓ Was returned
filename = filename || 'input';
filename = filename || 'input';
var file = this._createJsFileInstance(filename, source);
var errors = new Errors(file);
Function (anonymous_38)
✓ Was called
file.getParseErrors().forEach(function(parseError) {···
if (!this._maxErrorsExceeded) {
this._addParseError(errors, parseError, file);
}
}, this);
file.getParseErrors().forEach(function(parseError) {
Branch IfStatement
✓ Positive was executed (if)
if (!this._maxErrorsExceeded) {···
this._addParseError(errors, parseError, file);
}
✗ Negative was not executed (else)
}···
}, this);
if (!this._maxErrorsExceeded) {
this._addParseError(errors, parseError, file);
}
}, this);
Branch IfStatement
✓ Positive was executed (if)
if (!file._program || file._program.firstChild.type === 'EOF') {···
return errors;
}
✓ Negative was executed (else)
}···

this._checkJsFile(file, errors);
Branch LogicalExpression
✓ Was returned
if (!file._program || file._program.firstChild.type === 'EOF') {
✗ Was not returned
if (!file._program || file._program.firstChild.type === 'EOF') {
if (!file._program || file._program.firstChild.type === 'EOF') {
return errors;
}
this._checkJsFile(file, errors);
return errors;
},
/**
* Apply fix for common errors.
*
* @param {Error} error
* @return {Boolean} whether the correction was carried out
* @private
*/
Function (anonymous_39)
✓ Was called
_fixCommonError: function(error) {···
if (error.fix) {
// "error.fixed = true" should go first, so rule can
// decide for itself (with "error.fixed = false")
// if it can fix this particular error
error.fixed = true;
error.fix();
}

return !!error.fixed;
},
_fixCommonError: function(error) {
Branch IfStatement
✓ Positive was executed (if)
if (error.fix) {···
// "error.fixed = true" should go first, so rule can
// decide for itself (with "error.fixed = false")
// if it can fix this particular error
error.fixed = true;
error.fix();
}
✓ Negative was executed (else)
}···

return !!error.fixed;
if (error.fix) {
// "error.fixed = true" should go first, so rule can
// decide for itself (with "error.fixed = false")
// if it can fix this particular error
error.fixed = true;
error.fix();
}
return !!error.fixed;
},
/**
* Apply fix for specific error.
*
* @param {JsFile} file
* @param {Error} error
* @return {Boolean} whether the correction was carried out
* @private
*/
Function (anonymous_40)
✓ Was called
_fixSpecificError: function(file, error) {···
var configuration = this.getConfiguration();
var instance = configuration.getConfiguredRule(error.rule);

if (instance && instance._fix) {
// "error.fixed = true" should go first, so rule can
// decide for itself (with "error.fixed = false")
// if it can fix this particular error
error.fixed = true;
instance._fix(file, error);
}

return !!error.fixed;
},
_fixSpecificError: function(file, error) {
var configuration = this.getConfiguration();
var instance = configuration.getConfiguredRule(error.rule);
Branch IfStatement
✓ Positive was executed (if)
if (instance && instance._fix) {···
// "error.fixed = true" should go first, so rule can
// decide for itself (with "error.fixed = false")
// if it can fix this particular error
error.fixed = true;
instance._fix(file, error);
}
✓ Negative was executed (else)
}···

return !!error.fixed;
Branch LogicalExpression
✓ Was returned
if (instance && instance._fix) {
✗ Was not returned
if (instance && instance._fix) {
if (instance && instance._fix) {
// "error.fixed = true" should go first, so rule can
// decide for itself (with "error.fixed = false")
// if it can fix this particular error
error.fixed = true;
instance._fix(file, error);
}
return !!error.fixed;
},
/**
* Apply specific and common fixes.
*
* @param {JsFile} file
* @param {Errors} errors
* @protected
*/
Function (anonymous_41)
✓ Was called
_fixJsFile: function(file, errors) {···
errors.getErrorList().forEach(function(error) {
if (error.fixed) {
return;
}

try {
// Try to apply fixes for common errors
var isFixed = this._fixCommonError(error);

// Apply specific fix
if (!isFixed) {
this._fixSpecificError(file, error);
}
} catch (e) {
error.fixed = false;
errors.add(
getInternalErrorMessage(error.rule, e),
file.getProgram()
);
}
}, this);
},
_fixJsFile: function(file, errors) {
Function (anonymous_42)
✓ Was called
errors.getErrorList().forEach(function(error) {···
if (error.fixed) {
return;
}

try {
// Try to apply fixes for common errors
var isFixed = this._fixCommonError(error);

// Apply specific fix
if (!isFixed) {
this._fixSpecificError(file, error);
}
} catch (e) {
error.fixed = false;
errors.add(
getInternalErrorMessage(error.rule, e),
file.getProgram()
);
}
}, this);
errors.getErrorList().forEach(function(error) {
Branch IfStatement
✗ Positive was not executed (if)
if (error.fixed) {···
return;
}
✓ Negative was executed (else)
}···

try {
if (error.fixed) {
return;
}
try {
// Try to apply fixes for common errors
var isFixed = this._fixCommonError(error);
// Apply specific fix
Branch IfStatement
✓ Positive was executed (if)
if (!isFixed) {···
this._fixSpecificError(file, error);
}
✓ Negative was executed (else)
}···
} catch (e) {
if (!isFixed) {
this._fixSpecificError(file, error);
}
} catch (e) {
error.fixed = false;
errors.add(
getInternalErrorMessage(error.rule, e),
file.getProgram()
);
}
}, this);
},
/**
* Checks a file specified using JsFile instance.
* Fills Errors instance with validation errors.
*
* @param {JsFile} file
* @param {Errors} errors
* @protected
*/
Function (anonymous_43)
✓ Was called
_checkJsFile: function(file, errors) {···
if (this._maxErrorsExceeded) {
return;
}

var errorFilter = this._configuration.getErrorFilter();

this._configuredRules.forEach(function(rule) {
errors.setCurrentRule(rule.getOptionName());

try {
rule.check(file, errors);
} catch (e) {
errors.setCurrentRule('internalError');
errors.add(getInternalErrorMessage(rule.getOptionName(), e), file.getProgram());
}
}, this);

this._configuration.getUnsupportedRuleNames().forEach(function(rulename) {
errors.add('Unsupported rule: ' + rulename, file.getProgram());
});

var program = file.getProgram();
var tokenIndex = new TokenIndex(program.getFirstToken());
errors.calculateErrorLocations(tokenIndex);
errors.filter(function(error) {
if (error.element) {
return tokenIndex.isRuleEnabled(error.rule, error.element);
} else {
return true;
}
});

// sort errors list to show errors as they appear in source
errors.getErrorList().sort(function(a, b) {
return (a.line - b.line) || (a.column - b.column);
});

if (errorFilter) {
errors.filter(errorFilter);
}

if (this.maxErrorsEnabled()) {
if (this._maxErrors === -1 || this._maxErrors === null) {
this._maxErrorsExceeded = false;

} else {
this._maxErrorsExceeded = this._errorsFound + errors.getErrorCount() > this._maxErrors;
errors.stripErrorList(Math.max(0, this._maxErrors - this._errorsFound));
}
}

this._errorsFound += errors.getErrorCount();
},
_checkJsFile: function(file, errors) {
Branch IfStatement
✓ Positive was executed (if)
if (this._maxErrorsExceeded) {···
return;
}
✓ Negative was executed (else)
}···

var errorFilter = this._configuration.getErrorFilter();
if (this._maxErrorsExceeded) {
return;
}
var errorFilter = this._configuration.getErrorFilter();
Function (anonymous_44)
✓ Was called
this._configuredRules.forEach(function(rule) {···
errors.setCurrentRule(rule.getOptionName());

try {
rule.check(file, errors);
} catch (e) {
errors.setCurrentRule('internalError');
errors.add(getInternalErrorMessage(rule.getOptionName(), e), file.getProgram());
}
}, this);
this._configuredRules.forEach(function(rule) {
errors.setCurrentRule(rule.getOptionName());
try {
rule.check(file, errors);
} catch (e) {
errors.setCurrentRule('internalError');
errors.add(getInternalErrorMessage(rule.getOptionName(), e), file.getProgram());
}
}, this);
Function (anonymous_45)
✓ Was called
this._configuration.getUnsupportedRuleNames().forEach(function(rulename) {···
errors.add('Unsupported rule: ' + rulename, file.getProgram());
});
this._configuration.getUnsupportedRuleNames().forEach(function(rulename) {
errors.add('Unsupported rule: ' + rulename, file.getProgram());
});
var program = file.getProgram();
var tokenIndex = new TokenIndex(program.getFirstToken());
errors.calculateErrorLocations(tokenIndex);
Function (anonymous_46)
✓ Was called
errors.filter(function(error) {···
if (error.element) {
return tokenIndex.isRuleEnabled(error.rule, error.element);
} else {
return true;
}
});
errors.filter(function(error) {
Branch IfStatement
✓ Positive was executed (if)
if (error.element) {···
return tokenIndex.isRuleEnabled(error.rule, error.element);
} else {
✓ Negative was executed (else)
} else {···
return true;
}
if (error.element) {
return tokenIndex.isRuleEnabled(error.rule, error.element);
} else {
return true;
}
});
// sort errors list to show errors as they appear in source
Function (anonymous_47)
✓ Was called
errors.getErrorList().sort(function(a, b) {···
return (a.line - b.line) || (a.column - b.column);
});
errors.getErrorList().sort(function(a, b) {
Branch LogicalExpression
✓ Was returned
return (a.line - b.line) || (a.column - b.column);
✓ Was returned
return (a.line - b.line) || (a.column - b.column);
return (a.line - b.line) || (a.column - b.column);
});
Branch IfStatement
✓ Positive was executed (if)
if (errorFilter) {···
errors.filter(errorFilter);
}
✓ Negative was executed (else)
}···

if (this.maxErrorsEnabled()) {
if (errorFilter) {
errors.filter(errorFilter);
}
Branch IfStatement
✓ Positive was executed (if)
if (this.maxErrorsEnabled()) {···
if (this._maxErrors === -1 || this._maxErrors === null) {
this._maxErrorsExceeded = false;

} else {
this._maxErrorsExceeded = this._errorsFound + errors.getErrorCount() > this._maxErrors;
errors.stripErrorList(Math.max(0, this._maxErrors - this._errorsFound));
}
}
✓ Negative was executed (else)
}···

this._errorsFound += errors.getErrorCount();
if (this.maxErrorsEnabled()) {
Branch IfStatement
✗ Positive was not executed (if)
if (this._maxErrors === -1 || this._maxErrors === null) {···
this._maxErrorsExceeded = false;

} else {
✓ Negative was executed (else)
} else {···
this._maxErrorsExceeded = this._errorsFound + errors.getErrorCount() > this._maxErrors;
errors.stripErrorList(Math.max(0, this._maxErrors - this._errorsFound));
}
Branch LogicalExpression
✓ Was returned
if (this._maxErrors === -1 || this._maxErrors === null) {
✗ Was not returned
if (this._maxErrors === -1 || this._maxErrors === null) {
if (this._maxErrors === -1 || this._maxErrors === null) {
this._maxErrorsExceeded = false;
} else {
this._maxErrorsExceeded = this._errorsFound + errors.getErrorCount() > this._maxErrors;
errors.stripErrorList(Math.max(0, this._maxErrors - this._errorsFound));
}
}
this._errorsFound += errors.getErrorCount();
},
/**
* Adds parse error to the error list.
*
* @param {Errors} errors
* @param {Error} parseError
* @param {JsFile} file
* @private
*/
Function (anonymous_48)
✓ Was called
_addParseError: function(errors, parseError, file) {···
if (this._maxErrorsExceeded) {
return;
}

errors.add(parseError, file.getProgram());

if (this.maxErrorsEnabled()) {
this._errorsFound += 1;
this._maxErrorsExceeded = this._errorsFound >= this._maxErrors;
}
},
_addParseError: function(errors, parseError, file) {
Branch IfStatement
✗ Positive was not executed (if)
if (this._maxErrorsExceeded) {···
return;
}
✓ Negative was executed (else)
}···

errors.add(parseError, file.getProgram());
if (this._maxErrorsExceeded) {
return;
}
errors.add(parseError, file.getProgram());
Branch IfStatement
✓ Positive was executed (if)
if (this.maxErrorsEnabled()) {···
this._errorsFound += 1;
this._maxErrorsExceeded = this._errorsFound >= this._maxErrors;
}
✗ Negative was not executed (else)
}···
},
if (this.maxErrorsEnabled()) {
this._errorsFound += 1;
this._maxErrorsExceeded = this._errorsFound >= this._maxErrors;
}
},
/**
* Creates configured JsFile instance.
*
* @param {String} filename
* @param {String} source
* @private
*/
Function (anonymous_49)
✓ Was called
_createJsFileInstance: function(filename, source) {···
return new JsFile({
filename: filename,
source: source,
es3: this._configuration.isES3Enabled()
});
},
_createJsFileInstance: function(filename, source) {
return new JsFile({
filename: filename,
source: source,
es3: this._configuration.isES3Enabled()
});
},
/**
* Checks and fix file provided with a string.
*
* @param {String} source
* @param {String} [filename='input']
* @returns {{output: String, errors: Errors}}
*/
Function (anonymous_50)
✓ Was called
fixString: function(source, filename) {···
filename = filename || 'input';

var file = this._createJsFileInstance(filename, source);
var errors = new Errors(file);

var parseErrors = file.getParseErrors();
if (parseErrors.length > 0) {
parseErrors.forEach(function(parseError) {
this._addParseError(errors, parseError, file);
}, this);

return {output: source, errors: errors};
} else {
var attempt = 0;
do {

// Fill in errors list
this._checkJsFile(file, errors);

// Apply fixes
this._fixJsFile(file, errors);

var hasFixes = errors.getErrorList().some(function(err) {
return err.fixed;
});

if (!hasFixes) {
break;
}

file = this._createJsFileInstance(filename, file.render());
errors = new Errors(file);
attempt++;
} while (attempt < MAX_FIX_ATTEMPTS);

return {output: file.getSource(), errors: errors};
}
},
fixString: function(source, filename) {
Branch LogicalExpression
✓ Was returned
filename = filename || 'input';
✓ Was returned
filename = filename || 'input';
filename = filename || 'input';
var file = this._createJsFileInstance(filename, source);
var errors = new Errors(file);
var parseErrors = file.getParseErrors();
Branch IfStatement
✓ Positive was executed (if)
if (parseErrors.length > 0) {···
parseErrors.forEach(function(parseError) {
this._addParseError(errors, parseError, file);
}, this);

return {output: source, errors: errors};
} else {
✓ Negative was executed (else)
} else {···
var attempt = 0;
do {

// Fill in errors list
this._checkJsFile(file, errors);

// Apply fixes
this._fixJsFile(file, errors);

var hasFixes = errors.getErrorList().some(function(err) {
return err.fixed;
});

if (!hasFixes) {
break;
}

file = this._createJsFileInstance(filename, file.render());
errors = new Errors(file);
attempt++;
} while (attempt < MAX_FIX_ATTEMPTS);

return {output: file.getSource(), errors: errors};
}
if (parseErrors.length > 0) {
Function (anonymous_51)
✓ Was called
parseErrors.forEach(function(parseError) {···
this._addParseError(errors, parseError, file);
}, this);
parseErrors.forEach(function(parseError) {
this._addParseError(errors, parseError, file);
}, this);
return {output: source, errors: errors};
} else {
var attempt = 0;
do {
// Fill in errors list
this._checkJsFile(file, errors);
// Apply fixes
this._fixJsFile(file, errors);
Function (anonymous_52)
✓ Was called
var hasFixes = errors.getErrorList().some(function(err) {···
return err.fixed;
});
var hasFixes = errors.getErrorList().some(function(err) {
return err.fixed;
});
Branch IfStatement
✓ Positive was executed (if)
if (!hasFixes) {···
break;
}
✓ Negative was executed (else)
}···

file = this._createJsFileInstance(filename, file.render());
if (!hasFixes) {
break;
}
file = this._createJsFileInstance(filename, file.render());
errors = new Errors(file);
attempt++;
} while (attempt < MAX_FIX_ATTEMPTS);
return {output: file.getSource(), errors: errors};
}
},
/**
* Returns `true` if max erros limit is enabled.
*
* @returns {Boolean}
*/
Function (anonymous_53)
✓ Was called
maxErrorsEnabled: function() {···
return this._maxErrors !== null && this._maxErrors !== -1;
},
maxErrorsEnabled: function() {
Branch LogicalExpression
✓ Was returned
return this._maxErrors !== null && this._maxErrors !== -1;
✓ Was returned
return this._maxErrors !== null && this._maxErrors !== -1;
return this._maxErrors !== null && this._maxErrors !== -1;
},
/**
* Returns `true` if error count exceeded `maxErrors` option value.
*
* @returns {Boolean}
*/
Function (anonymous_54)
✓ Was called
maxErrorsExceeded: function() {···
return this._maxErrorsExceeded;
},
maxErrorsExceeded: function() {
return this._maxErrorsExceeded;
},
/**
* Returns new configuration instance.
*
* @protected
* @returns {Configuration}
*/
Function (anonymous_55)
✓ Was called
_createConfiguration: function() {···
return new Configuration();
},
_createConfiguration: function() {
return new Configuration();
},
/**
* Returns current configuration instance.
*
* @returns {Configuration}
*/
Function (anonymous_56)
✓ Was called
getConfiguration: function() {···
return this._configuration;
}
getConfiguration: function() {
return this._configuration;
}
};
module.exports = StringChecker;
errors.js
var chalk = require('chalk');
var TokenAssert = require('./token-assert');
var LINE_SEPARATOR = /\r\n|\r|\n/g;
var EMPTY_POS = {
line: 1,
column: 0
};
/**
* Set of errors for specified file.
*
* @name Errors
* @param {JsFile} file
*/
Function (anonymous_57)
✓ Was called
var Errors = function(file) {···
this._errorList = [];
this._file = file;
this._currentRule = '';

/**
* @type {TokenAssert}
* @public
*/
this.assert = new TokenAssert(file);
this.assert.on('error', this._addError.bind(this));
};
var Errors = function(file) {
this._errorList = [];
this._file = file;
this._currentRule = '';
/**
* @type {TokenAssert}
* @public
*/
this.assert = new TokenAssert(file);
this.assert.on('error', this._addError.bind(this));
};
Errors.prototype = {
/**
* Adds style error to the list
*
* @param {String | Error} message
* @param {cst.types.Element} element
* @param {Number} [offset] relative offset
*/
Function (anonymous_58)
✓ Was called
add: function(message, element, offset) {···
if (message instanceof Error) {
this._addParseError(message);
return;
}

this._addError({
message: message,
element: element,
offset: offset
});
},
add: function(message, element, offset) {
Branch IfStatement
✓ Positive was executed (if)
if (message instanceof Error) {···
this._addParseError(message);
return;
}
✓ Negative was executed (else)
}···

this._addError({
if (message instanceof Error) {
this._addParseError(message);
return;
}
this._addError({
message: message,
element: element,
offset: offset
});
},
/**
* Adds style error to the list
*
* @param {Object} errorInfo
*/
Function (anonymous_59)
✓ Was called
cast: function(errorInfo) {···
this._addError(errorInfo);
},
cast: function(errorInfo) {
this._addError(errorInfo);
},
/**
* Adds parser error to error list.
*
* @param {Object} errorInfo
* @private
*/
Function (anonymous_60)
✓ Was called
_addParseError: function(errorInfo) {···
this._errorList.push({
filename: this._file.getFilename(),
rule: 'parseError',
message: errorInfo.message,
line: errorInfo.loc ? errorInfo.loc.line : 1,
column: errorInfo.loc ? errorInfo.loc.column : 0
});
},
_addParseError: function(errorInfo) {
this._errorList.push({
filename: this._file.getFilename(),
rule: 'parseError',
message: errorInfo.message,
Branch ConditionalExpression
✓ Positive was returned (? ...)
line: errorInfo.loc ? errorInfo.loc.line : 1,
✓ Negative was returned (: ...)
line: errorInfo.loc ? errorInfo.loc.line : 1,
line: errorInfo.loc ? errorInfo.loc.line : 1,
Branch ConditionalExpression
✓ Positive was returned (? ...)
column: errorInfo.loc ? errorInfo.loc.column : 0
✓ Negative was returned (: ...)
column: errorInfo.loc ? errorInfo.loc.column : 0
column: errorInfo.loc ? errorInfo.loc.column : 0
});
},
/**
* Adds error to error list.
*
* @param {Object} errorInfo
* @private
*/
Function (anonymous_61)
✓ Was called
_addError: function(errorInfo) {···
this._errorList.push({
filename: this._file.getFilename(),
rule: this._currentRule,
message: this._prepareMessage(errorInfo),
element: errorInfo.element,
offset: errorInfo.offset,
additional: errorInfo.additional,
fixed: false,
fix: errorInfo.fix
});
},
_addError: function(errorInfo) {
this._errorList.push({
filename: this._file.getFilename(),
rule: this._currentRule,
message: this._prepareMessage(errorInfo),
element: errorInfo.element,
offset: errorInfo.offset,
additional: errorInfo.additional,
fixed: false,
fix: errorInfo.fix
});
},
/**
* Prepare error message.
*
* @param {Object} errorInfo
* @private
*/
Function (anonymous_62)
✓ Was called
_prepareMessage: function(errorInfo) {···
var rule = errorInfo instanceof Error ? 'parseError' : this._currentRule;

if (rule) {
return rule + ': ' + errorInfo.message;
}

return errorInfo.message;
},
_prepareMessage: function(errorInfo) {
Branch ConditionalExpression
✗ Positive was not returned (? ...)
var rule = errorInfo instanceof Error ? 'parseError' : this._currentRule;
✓ Negative was returned (: ...)
var rule = errorInfo instanceof Error ? 'parseError' : this._currentRule;
var rule = errorInfo instanceof Error ? 'parseError' : this._currentRule;
Branch IfStatement
✓ Positive was executed (if)
if (rule) {···
return rule + ': ' + errorInfo.message;
}
✓ Negative was executed (else)
}···

return errorInfo.message;
if (rule) {
return rule + ': ' + errorInfo.message;
}
return errorInfo.message;
},
/**
* Returns style error list.
*
* @returns {Object[]}
*/
Function (anonymous_63)
✓ Was called
getErrorList: function() {···
return this._errorList;
},
getErrorList: function() {
return this._errorList;
},
/**
* Returns filename of file this error list is for.
*
* @returns {String}
*/
Function (anonymous_64)
✓ Was called
getFilename: function() {···
return this._file.getFilename();
},
getFilename: function() {
return this._file.getFilename();
},
/**
* Returns true if no errors are added.
*
* @returns {Boolean}
*/
Function (anonymous_65)
✗ Was not called
isEmpty: function() {···
return this._errorList.length === 0;
},
isEmpty: function() {
return this._errorList.length === 0;
},
/**
* Returns amount of errors added by the rules.
*
* @returns {Number}
*/
Function (anonymous_66)
✗ Was not called
getValidationErrorCount: function() {···
return this._errorList.filter(function(error) {
return error.rule !== 'parseError' && error.rule !== 'internalError';
});
},
getValidationErrorCount: function() {
Function (anonymous_67)
✗ Was not called
return this._errorList.filter(function(error) {···
return error.rule !== 'parseError' && error.rule !== 'internalError';
});
return this._errorList.filter(function(error) {
Branch LogicalExpression
✗ Was not returned
return error.rule !== 'parseError' && error.rule !== 'internalError';
✗ Was not returned
return error.rule !== 'parseError' && error.rule !== 'internalError';
return error.rule !== 'parseError' && error.rule !== 'internalError';
});
},
/**
* Returns amount of errors added by the rules.
*
* @returns {Number}
*/
Function (anonymous_68)
✓ Was called
getErrorCount: function() {···
return this._errorList.length;
},
getErrorCount: function() {
return this._errorList.length;
},
/**
* Strips error list to the specified length.
*
* @param {Number} length
*/
Function (anonymous_69)
✓ Was called
stripErrorList: function(length) {···
this._errorList.splice(length);
},
stripErrorList: function(length) {
this._errorList.splice(length);
},
/**
* Filters out errors based on the supplied filter function
*
* @param {Function} filter
*/
Function (anonymous_70)
✓ Was called
filter: function(filter) {···
this._errorList = this._errorList.filter(filter);
},
filter: function(filter) {
this._errorList = this._errorList.filter(filter);
},
/**
* @param {TokenIndex} tokenIndex
*/
Function (anonymous_71)
✓ Was called
calculateErrorLocations: function(tokenIndex) {···
this._errorList.forEach(function(error) {
var pos = Errors.getPosition(error, tokenIndex);
error.line = pos.line;
error.column = pos.column;
});
},
calculateErrorLocations: function(tokenIndex) {
Function (anonymous_72)
✓ Was called
this._errorList.forEach(function(error) {···
var pos = Errors.getPosition(error, tokenIndex);
error.line = pos.line;
error.column = pos.column;
});
this._errorList.forEach(function(error) {
var pos = Errors.getPosition(error, tokenIndex);
error.line = pos.line;
error.column = pos.column;
});
},
/**
* Formats error for further output.
*
* @param {Object} error
* @param {Boolean} [colorize = false]
* @returns {String}
*/
Function (anonymous_73)
✓ Was called
explainError: function(error, colorize) {···
var lineNumber = error.line - 1;
var lines = this._file.getLines();
var result = [
renderLine(lineNumber, lines[lineNumber], colorize),
renderPointer(error.column, colorize)
];
var i = lineNumber - 1;
var linesAround = 2;
while (i >= 0 && i >= (lineNumber - linesAround)) {
result.unshift(renderLine(i, lines[i], colorize));
i--;
}
i = lineNumber + 1;
while (i < lines.length && i <= (lineNumber + linesAround)) {
result.push(renderLine(i, lines[i], colorize));
i++;
}
result.unshift(formatErrorMessage(error.message, this.getFilename(), colorize));
return result.join('\n');
},
explainError: function(error, colorize) {
var lineNumber = error.line - 1;
var lines = this._file.getLines();
var result = [
renderLine(lineNumber, lines[lineNumber], colorize),
renderPointer(error.column, colorize)
];
var i = lineNumber - 1;
var linesAround = 2;
Branch LogicalExpression
✓ Was returned
while (i >= 0 && i >= (lineNumber - linesAround)) {
✓ Was returned
while (i >= 0 && i >= (lineNumber - linesAround)) {
while (i >= 0 && i >= (lineNumber - linesAround)) {
result.unshift(renderLine(i, lines[i], colorize));
i--;
}
i = lineNumber + 1;
Branch LogicalExpression
✓ Was returned
while (i < lines.length && i <= (lineNumber + linesAround)) {
✓ Was returned
while (i < lines.length && i <= (lineNumber + linesAround)) {
while (i < lines.length && i <= (lineNumber + linesAround)) {
result.push(renderLine(i, lines[i], colorize));
i++;
}
result.unshift(formatErrorMessage(error.message, this.getFilename(), colorize));
return result.join('\n');
},
/**
* Sets the current rule so that errors are aware
* of which rule triggered them.
*
* @param {String} rule
*/
Function (anonymous_74)
✓ Was called
setCurrentRule: function(rule) {···
this._currentRule = rule;
}
setCurrentRule: function(rule) {
this._currentRule = rule;
}
};
/**
* Formats error message header.
*
* @param {String} message
* @param {String} filename
* @param {Boolean} colorize
* @returns {String}
*/
Function formatErrorMessage
✓ Was called
function formatErrorMessage(message, filename, colorize) {···
return (colorize ? chalk.bold(message) : message) +
' at ' +
(colorize ? chalk.green(filename) : filename) + ' :';
}
function formatErrorMessage(message, filename, colorize) {
Branch ConditionalExpression
✓ Positive was returned (? ...)
return (colorize ? chalk.bold(message) : message) +
✓ Negative was returned (: ...)
return (colorize ? chalk.bold(message) : message) +
return (colorize ? chalk.bold(message) : message) +
' at ' +
Branch ConditionalExpression
✓ Positive was returned (? ...)
(colorize ? chalk.green(filename) : filename) + ' :';
✓ Negative was returned (: ...)
(colorize ? chalk.green(filename) : filename) + ' :';
(colorize ? chalk.green(filename) : filename) + ' :';
}
/**
* Simple util for prepending spaces to the string until it fits specified size.
*
* @param {String} s
* @param {Number} len
* @returns {String}
*/
Function prependSpaces
✓ Was called
function prependSpaces(s, len) {···
while (s.length < len) {
s = ' ' + s;
}
return s;
}
function prependSpaces(s, len) {
while (s.length < len) {
s = ' ' + s;
}
return s;
}
/**
* Renders single line of code in style error formatted output.
*
* @param {Number} n line number
* @param {String} line
* @param {Boolean} [colorize = false]
* @returns {String}
*/
Function renderLine
✓ Was called
function renderLine(n, line, colorize) {···
// Convert tabs to spaces, so errors in code lines with tabs as indention symbol
// could be correctly rendered, plus it will provide less verbose output
line = line.replace(/\t/g, ' ');

// "n + 1" to print lines in human way (counted from 1)
var lineNumber = prependSpaces((n + 1).toString(), 5) + ' |';
return ' ' + (colorize ? chalk.grey(lineNumber) : lineNumber) + line;
}
function renderLine(n, line, colorize) {
// Convert tabs to spaces, so errors in code lines with tabs as indention symbol
// could be correctly rendered, plus it will provide less verbose output
line = line.replace(/\t/g, ' ');
// "n + 1" to print lines in human way (counted from 1)
var lineNumber = prependSpaces((n + 1).toString(), 5) + ' |';
Branch ConditionalExpression
✓ Positive was returned (? ...)
return ' ' + (colorize ? chalk.grey(lineNumber) : lineNumber) + line;
✓ Negative was returned (: ...)
return ' ' + (colorize ? chalk.grey(lineNumber) : lineNumber) + line;
return ' ' + (colorize ? chalk.grey(lineNumber) : lineNumber) + line;
}
/**
* Renders pointer:
* ---------------^
*
* @param {Number} column
* @param {Boolean} [colorize = false]
* @returns {String}
*/
Function renderPointer
✓ Was called
function renderPointer(column, colorize) {···
var res = (new Array(column + 9)).join('-') + '^';
return colorize ? chalk.grey(res) : res;
}
function renderPointer(column, colorize) {
var res = (new Array(column + 9)).join('-') + '^';
Branch ConditionalExpression
✓ Positive was returned (? ...)
return colorize ? chalk.grey(res) : res;
✓ Negative was returned (: ...)
return colorize ? chalk.grey(res) : res;
return colorize ? chalk.grey(res) : res;
}
/**
* Get position of the element
*
* @param {Error} [error]
* @param {TokenIndex} [tokenIndex]
* @return {Object}
*/
Function (anonymous_79)
✓ Was called
Errors.getPosition = function(error, tokenIndex) {···
var element = error.element;
var offset = error.offset;
var rule = error.rule;

if (!element) {
return EMPTY_POS;
}

if (offset === undefined) {
// TODO: probably should be generalized
if (rule === 'validateQuoteMarks') {
offset = 0;
} else if (element.getSourceCodeLength() === 1) {
offset = 0;
} else {
offset = (element.getNewlineCount() === 0 && Math.ceil(element.getSourceCodeLength() / 2)) || 0;
}
}

var pos = tokenIndex ? tokenIndex.getElementLoc(element) : element.getLoc().start;
if (!pos) {
return EMPTY_POS;
}

if (offset === 0) {
return pos;
}

var newlineCount = element.getNewlineCount();
if (newlineCount > 0) {
var code = element.getSourceCode();
LINE_SEPARATOR.lastIndex = 0;
var lineOffset = 0;
var match;
var previousOffset = 0;
var firstLineColumnOffset = pos.column;
while ((match = LINE_SEPARATOR.exec(code)) !== null) {
var currentOffset = match.index;
if (offset <= currentOffset) {
return {
line: pos.line + lineOffset,
column: firstLineColumnOffset + offset - previousOffset
};
}
previousOffset = currentOffset + match[0].length;
firstLineColumnOffset = 0;
lineOffset++;
}
return {
line: pos.line + newlineCount,
column: offset - previousOffset
};
} else {
return {
line: pos.line,
column: pos.column + offset
};
}
};
Errors.getPosition = function(error, tokenIndex) {
var element = error.element;
var offset = error.offset;
var rule = error.rule;
Branch IfStatement
✗ Positive was not executed (if)
if (!element) {···
return EMPTY_POS;
}
✓ Negative was executed (else)
}···

if (offset === undefined) {
if (!element) {
return EMPTY_POS;
}
Branch IfStatement
✓ Positive was executed (if)
if (offset === undefined) {···
// TODO: probably should be generalized
if (rule === 'validateQuoteMarks') {
offset = 0;
} else if (element.getSourceCodeLength() === 1) {
offset = 0;
} else {
offset = (element.getNewlineCount() === 0 && Math.ceil(element.getSourceCodeLength() / 2)) || 0;
}
}
✗ Negative was not executed (else)
}···

var pos = tokenIndex ? tokenIndex.getElementLoc(element) : element.getLoc().start;
if (offset === undefined) {
// TODO: probably should be generalized
Branch IfStatement
✓ Positive was executed (if)
if (rule === 'validateQuoteMarks') {···
offset = 0;
} else if (element.getSourceCodeLength() === 1) {
✓ Negative was executed (else)
} else if (element.getSourceCodeLength() === 1) {···
offset = 0;
} else {
offset = (element.getNewlineCount() === 0 && Math.ceil(element.getSourceCodeLength() / 2)) || 0;
}
if (rule === 'validateQuoteMarks') {
offset = 0;
Branch IfStatement
✓ Positive was executed (if)
} else if (element.getSourceCodeLength() === 1) {···
offset = 0;
} else {
✓ Negative was executed (else)
} else {···
offset = (element.getNewlineCount() === 0 && Math.ceil(element.getSourceCodeLength() / 2)) || 0;
}
} else if (element.getSourceCodeLength() === 1) {
offset = 0;
} else {
Branch LogicalExpression
✗ Was not returned
offset = (element.getNewlineCount() === 0 && Math.ceil(element.getSourceCodeLength() / 2)) || 0;
✓ Was returned
offset = (element.getNewlineCount() === 0 && Math.ceil(element.getSourceCodeLength() / 2)) || 0;
Branch LogicalExpression
✓ Was returned
offset = (element.getNewlineCount() === 0 && Math.ceil(element.getSourceCodeLength() / 2)) || 0;
✗ Was not returned
offset = (element.getNewlineCount() === 0 && Math.ceil(element.getSourceCodeLength() / 2)) || 0;
offset = (element.getNewlineCount() === 0 && Math.ceil(element.getSourceCodeLength() / 2)) || 0;
}
}
Branch ConditionalExpression
✓ Positive was returned (? ...)
var pos = tokenIndex ? tokenIndex.getElementLoc(element) : element.getLoc().start;
✓ Negative was returned (: ...)
var pos = tokenIndex ? tokenIndex.getElementLoc(element) : element.getLoc().start;
var pos = tokenIndex ? tokenIndex.getElementLoc(element) : element.getLoc().start;
Branch IfStatement
✗ Positive was not executed (if)
if (!pos) {···
return EMPTY_POS;
}
✓ Negative was executed (else)
}···

if (offset === 0) {
if (!pos) {
return EMPTY_POS;
}
Branch IfStatement
✓ Positive was executed (if)
if (offset === 0) {···
return pos;
}
✓ Negative was executed (else)
}···

var newlineCount = element.getNewlineCount();
if (offset === 0) {
return pos;
}
var newlineCount = element.getNewlineCount();
Branch IfStatement
✗ Positive was not executed (if)
if (newlineCount > 0) {···
var code = element.getSourceCode();
LINE_SEPARATOR.lastIndex = 0;
var lineOffset = 0;
var match;
var previousOffset = 0;
var firstLineColumnOffset = pos.column;
while ((match = LINE_SEPARATOR.exec(code)) !== null) {
var currentOffset = match.index;
if (offset <= currentOffset) {
return {
line: pos.line + lineOffset,
column: firstLineColumnOffset + offset - previousOffset
};
}
previousOffset = currentOffset + match[0].length;
firstLineColumnOffset = 0;
lineOffset++;
}
return {
line: pos.line + newlineCount,
column: offset - previousOffset
};
} else {
✓ Negative was executed (else)
} else {···
return {
line: pos.line,
column: pos.column + offset
};
}
if (newlineCount > 0) {
var code = element.getSourceCode();
LINE_SEPARATOR.lastIndex = 0;
var lineOffset = 0;
var match;
var previousOffset = 0;
var firstLineColumnOffset = pos.column;
while ((match = LINE_SEPARATOR.exec(code)) !== null) {
var currentOffset = match.index;
Branch IfStatement
✗ Positive was not executed (if)
if (offset <= currentOffset) {···
return {
line: pos.line + lineOffset,
column: firstLineColumnOffset + offset - previousOffset
};
}
✗ Negative was not executed (else)
}···
previousOffset = currentOffset + match[0].length;
if (offset <= currentOffset) {
return {
line: pos.line + lineOffset,
column: firstLineColumnOffset + offset - previousOffset
};
}
previousOffset = currentOffset + match[0].length;
firstLineColumnOffset = 0;
lineOffset++;
}
return {
line: pos.line + newlineCount,
column: offset - previousOffset
};
} else {
return {
line: pos.line,
column: pos.column + offset
};
}
};
module.exports = Errors;
token-assert.js
var utils = require('util');
var EventEmitter = require('events').EventEmitter;
var Token = require('cst').Token;
/**
* Token assertions class.
*
* @name {TokenAssert}
* @param {JsFile} file
*/
Function TokenAssert
✓ Was called
function TokenAssert(file) {···
EventEmitter.call(this);

this._file = file;
}
function TokenAssert(file) {
EventEmitter.call(this);
this._file = file;
}
utils.inherits(TokenAssert, EventEmitter);
/**
* Requires to have whitespace between specified tokens. Ignores newlines.
*
* @param {Object} options
* @param {Object} options.token
* @param {Object} options.nextToken
* @param {String} [options.message]
* @param {Number} [options.spaces] Amount of spaces between tokens.
* @return {Boolean} whether an error was found
*/
Function (anonymous_81)
✓ Was called
TokenAssert.prototype.whitespaceBetween = function(options) {···
options.atLeast = 1;
return this.spacesBetween(options);
};
TokenAssert.prototype.whitespaceBetween = function(options) {
options.atLeast = 1;
return this.spacesBetween(options);
};
/**
* Requires to have no whitespace between specified tokens.
*
* @param {Object} options
* @param {Object} options.token
* @param {Object} options.nextToken
* @param {String} [options.message]
* @param {Boolean} [options.disallowNewLine=false]
* @return {Boolean} whether an error was found
*/
Function (anonymous_82)
✓ Was called
TokenAssert.prototype.noWhitespaceBetween = function(options) {···
options.exactly = 0;
return this.spacesBetween(options);
};
TokenAssert.prototype.noWhitespaceBetween = function(options) {
options.exactly = 0;
return this.spacesBetween(options);
};
/**
* Requires to have the whitespace between specified tokens with the provided options.
*
* @param {Object} options
* @param {Object} options.token
* @param {Object} options.nextToken
* @param {String} [options.message]
* @param {Object} [options.atLeast] At least how many spaces the tokens are apart
* @param {Object} [options.atMost] At most how many spaces the tokens are apart
* @param {Object} [options.exactly] Exactly how many spaces the tokens are apart
* @param {Boolean} [options.disallowNewLine=false]
* @return {Boolean} whether an error was found
*/
Function (anonymous_83)
✓ Was called
TokenAssert.prototype.spacesBetween = function(options) {···
var token = options.token;
var nextToken = options.nextToken;
var atLeast = options.atLeast;
var atMost = options.atMost;
var exactly = options.exactly;

if (!token || !nextToken) {
return false;
}

this._validateOptions(options);

if (!options.disallowNewLine && !this._file.isOnTheSameLine(token, nextToken)) {
return false;
}

// Only attempt to remove or add lines if there are no comments between the two nodes
// as this prevents accidentally moving a valid token onto a line comment ed line
var fixed = !options.token.getNextNonWhitespaceToken().isComment;

var emitError = function(countPrefix, spaceCount) {
var fix = function() {
this._file.setWhitespaceBefore(nextToken, new Array(spaceCount + 1).join(' '));
}.bind(this);

var msgPostfix = token.value + ' and ' + nextToken.value;

if (!options.message) {
if (exactly === 0) {
// support noWhitespaceBetween
options.message = 'Unexpected whitespace between ' + msgPostfix;
} else if (exactly !== undefined) {
// support whitespaceBetween (spaces option)
options.message = spaceCount + ' spaces required between ' + msgPostfix;
} else if (atLeast === 1 && atMost === undefined) {
// support whitespaceBetween (no spaces option)
options.message = 'Missing space between ' + msgPostfix;
} else {
options.message = countPrefix + ' ' + spaceCount + ' spaces required between ' + msgPostfix;
}
}

this.emit('error', {
message: options.message,
element: token,
offset: token.getSourceCodeLength(),
fix: fixed ? fix : undefined
});
}.bind(this);

var spacesBetween = this._file.getDistanceBetween(token, nextToken);

if (atLeast !== undefined && spacesBetween < atLeast) {
emitError('at least', atLeast);
return true;
}

if (atMost !== undefined && spacesBetween > atMost) {
emitError('at most', atMost);
return true;
}

if (exactly !== undefined && spacesBetween !== exactly) {
emitError('exactly', exactly);
return true;
}

return false;
};
TokenAssert.prototype.spacesBetween = function(options) {
var token = options.token;
var nextToken = options.nextToken;
var atLeast = options.atLeast;
var atMost = options.atMost;
var exactly = options.exactly;
Branch IfStatement
✓ Positive was executed (if)
if (!token || !nextToken) {···
return false;
}
✓ Negative was executed (else)
}···

this._validateOptions(options);
Branch LogicalExpression
✓ Was returned
if (!token || !nextToken) {
✓ Was returned
if (!token || !nextToken) {
if (!token || !nextToken) {
return false;
}
this._validateOptions(options);
Branch IfStatement
✓ Positive was executed (if)
if (!options.disallowNewLine && !this._file.isOnTheSameLine(token, nextToken)) {···
return false;
}
✓ Negative was executed (else)
}···

// Only attempt to remove or add lines if there are no comments between the two nodes
Branch LogicalExpression
✓ Was returned
if (!options.disallowNewLine && !this._file.isOnTheSameLine(token, nextToken)) {
✓ Was returned
if (!options.disallowNewLine && !this._file.isOnTheSameLine(token, nextToken)) {
if (!options.disallowNewLine && !this._file.isOnTheSameLine(token, nextToken)) {
return false;
}
// Only attempt to remove or add lines if there are no comments between the two nodes
// as this prevents accidentally moving a valid token onto a line comment ed line
var fixed = !options.token.getNextNonWhitespaceToken().isComment;
Function (anonymous_84)
✓ Was called
var emitError = function(countPrefix, spaceCount) {···
var fix = function() {
this._file.setWhitespaceBefore(nextToken, new Array(spaceCount + 1).join(' '));
}.bind(this);

var msgPostfix = token.value + ' and ' + nextToken.value;

if (!options.message) {
if (exactly === 0) {
// support noWhitespaceBetween
options.message = 'Unexpected whitespace between ' + msgPostfix;
} else if (exactly !== undefined) {
// support whitespaceBetween (spaces option)
options.message = spaceCount + ' spaces required between ' + msgPostfix;
} else if (atLeast === 1 && atMost === undefined) {
// support whitespaceBetween (no spaces option)
options.message = 'Missing space between ' + msgPostfix;
} else {
options.message = countPrefix + ' ' + spaceCount + ' spaces required between ' + msgPostfix;
}
}

this.emit('error', {
message: options.message,
element: token,
offset: token.getSourceCodeLength(),
fix: fixed ? fix : undefined
});
}.bind(this);
var emitError = function(countPrefix, spaceCount) {
Function (anonymous_85)
✗ Was not called
var fix = function() {···
this._file.setWhitespaceBefore(nextToken, new Array(spaceCount + 1).join(' '));
}.bind(this);
var fix = function() {
this._file.setWhitespaceBefore(nextToken, new Array(spaceCount + 1).join(' '));
}.bind(this);
var msgPostfix = token.value + ' and ' + nextToken.value;
Branch IfStatement
✓ Positive was executed (if)
if (!options.message) {···
if (exactly === 0) {
// support noWhitespaceBetween
options.message = 'Unexpected whitespace between ' + msgPostfix;
} else if (exactly !== undefined) {
// support whitespaceBetween (spaces option)
options.message = spaceCount + ' spaces required between ' + msgPostfix;
} else if (atLeast === 1 && atMost === undefined) {
// support whitespaceBetween (no spaces option)
options.message = 'Missing space between ' + msgPostfix;
} else {
options.message = countPrefix + ' ' + spaceCount + ' spaces required between ' + msgPostfix;
}
}
✓ Negative was executed (else)
}···

this.emit('error', {
if (!options.message) {
Branch IfStatement
✓ Positive was executed (if)
if (exactly === 0) {···
// support noWhitespaceBetween
options.message = 'Unexpected whitespace between ' + msgPostfix;
} else if (exactly !== undefined) {
✓ Negative was executed (else)
} else if (exactly !== undefined) {···
// support whitespaceBetween (spaces option)
options.message = spaceCount + ' spaces required between ' + msgPostfix;
} else if (atLeast === 1 && atMost === undefined) {
// support whitespaceBetween (no spaces option)
options.message = 'Missing space between ' + msgPostfix;
} else {
options.message = countPrefix + ' ' + spaceCount + ' spaces required between ' + msgPostfix;
}
if (exactly === 0) {
// support noWhitespaceBetween
options.message = 'Unexpected whitespace between ' + msgPostfix;
Branch IfStatement
✓ Positive was executed (if)
} else if (exactly !== undefined) {···
// support whitespaceBetween (spaces option)
options.message = spaceCount + ' spaces required between ' + msgPostfix;
} else if (atLeast === 1 && atMost === undefined) {
✓ Negative was executed (else)
} else if (atLeast === 1 && atMost === undefined) {···
// support whitespaceBetween (no spaces option)
options.message = 'Missing space between ' + msgPostfix;
} else {
options.message = countPrefix + ' ' + spaceCount + ' spaces required between ' + msgPostfix;
}
} else if (exactly !== undefined) {
// support whitespaceBetween (spaces option)
options.message = spaceCount + ' spaces required between ' + msgPostfix;
Branch IfStatement
✓ Positive was executed (if)
} else if (atLeast === 1 && atMost === undefined) {···
// support whitespaceBetween (no spaces option)
options.message = 'Missing space between ' + msgPostfix;
} else {
✓ Negative was executed (else)
} else {···
options.message = countPrefix + ' ' + spaceCount + ' spaces required between ' + msgPostfix;
}
Branch LogicalExpression
✓ Was returned
} else if (atLeast === 1 && atMost === undefined) {
✓ Was returned
} else if (atLeast === 1 && atMost === undefined) {
} else if (atLeast === 1 && atMost === undefined) {
// support whitespaceBetween (no spaces option)
options.message = 'Missing space between ' + msgPostfix;
} else {
options.message = countPrefix + ' ' + spaceCount + ' spaces required between ' + msgPostfix;
}
}
this.emit('error', {
message: options.message,
element: token,
offset: token.getSourceCodeLength(),
Branch ConditionalExpression
✓ Positive was returned (? ...)
fix: fixed ? fix : undefined
✓ Negative was returned (: ...)
fix: fixed ? fix : undefined
fix: fixed ? fix : undefined
});
}.bind(this);
var spacesBetween = this._file.getDistanceBetween(token, nextToken);
Branch IfStatement
✓ Positive was executed (if)
if (atLeast !== undefined && spacesBetween < atLeast) {···
emitError('at least', atLeast);
return true;
}
✓ Negative was executed (else)
}···

if (atMost !== undefined && spacesBetween > atMost) {
Branch LogicalExpression
✓ Was returned
if (atLeast !== undefined && spacesBetween < atLeast) {
✓ Was returned
if (atLeast !== undefined && spacesBetween < atLeast) {
if (atLeast !== undefined && spacesBetween < atLeast) {
emitError('at least', atLeast);
return true;
}
Branch IfStatement
✓ Positive was executed (if)
if (atMost !== undefined && spacesBetween > atMost) {···
emitError('at most', atMost);
return true;
}
✓ Negative was executed (else)
}···

if (exactly !== undefined && spacesBetween !== exactly) {
Branch LogicalExpression
✓ Was returned
if (atMost !== undefined && spacesBetween > atMost) {
✓ Was returned
if (atMost !== undefined && spacesBetween > atMost) {
if (atMost !== undefined && spacesBetween > atMost) {
emitError('at most', atMost);
return true;
}
Branch IfStatement
✓ Positive was executed (if)
if (exactly !== undefined && spacesBetween !== exactly) {···
emitError('exactly', exactly);
return true;
}
✓ Negative was executed (else)
}···

return false;
Branch LogicalExpression
✓ Was returned
if (exactly !== undefined && spacesBetween !== exactly) {
✓ Was returned
if (exactly !== undefined && spacesBetween !== exactly) {
if (exactly !== undefined && spacesBetween !== exactly) {
emitError('exactly', exactly);
return true;
}
return false;
};
/**
* Requires the specified line to have the expected indentation.
*
* @param {Object} options
* @param {Number} options.actual
* @param {Number} options.expected
* @param {String} options.indentChar
* @param {String} options.token
* @return {Boolean} whether an error was found
*/
Function (anonymous_86)
✓ Was called
TokenAssert.prototype.indentation = function(options) {···
var token = options.token;
var lineNumber = options.lineNumber;
var actual = options.actual;
var expected = options.expected;
var indentChar = options.indentChar;

if (actual === expected) {
return false;
}

this.emit('error', {
message: 'Expected indentation of ' + expected + ' characters',
line: lineNumber,
column: expected,
fix: function() {
var newWhitespace = (new Array(expected + 1)).join(indentChar);

this._updateWhitespaceByLine(token, function(lines) {
lines[lines.length - 1] = newWhitespace;
return lines;
});

if (token.isComment) {
this._updateCommentWhitespace(token, indentChar, actual, expected);
}
}.bind(this)
});

return true;
};
TokenAssert.prototype.indentation = function(options) {
var token = options.token;
var lineNumber = options.lineNumber;
var actual = options.actual;
var expected = options.expected;
var indentChar = options.indentChar;
Branch IfStatement
✓ Positive was executed (if)
if (actual === expected) {···
return false;
}
✓ Negative was executed (else)
}···

this.emit('error', {
if (actual === expected) {
return false;
}
this.emit('error', {
message: 'Expected indentation of ' + expected + ' characters',
line: lineNumber,
column: expected,
Function (anonymous_87)
✓ Was called
fix: function() {···
var newWhitespace = (new Array(expected + 1)).join(indentChar);

this._updateWhitespaceByLine(token, function(lines) {
lines[lines.length - 1] = newWhitespace;
return lines;
});

if (token.isComment) {
this._updateCommentWhitespace(token, indentChar, actual, expected);
}
}.bind(this)
fix: function() {
var newWhitespace = (new Array(expected + 1)).join(indentChar);
Function (anonymous_88)
✓ Was called
this._updateWhitespaceByLine(token, function(lines) {···
lines[lines.length - 1] = newWhitespace;
return lines;
});
this._updateWhitespaceByLine(token, function(lines) {
lines[lines.length - 1] = newWhitespace;
return lines;
});
Branch IfStatement
✓ Positive was executed (if)
if (token.isComment) {···
this._updateCommentWhitespace(token, indentChar, actual, expected);
}
✗ Negative was not executed (else)
}···
}.bind(this)
if (token.isComment) {
this._updateCommentWhitespace(token, indentChar, actual, expected);
}
}.bind(this)
});
return true;
};
/**
* Updates the whitespace of a line by passing split lines to a callback function
* for editing.
*
* @param {Object} token
* @param {Function} callback
*/
Function (anonymous_89)
✓ Was called
TokenAssert.prototype._updateWhitespaceByLine = function(token, callback) {···
var lineBreak = this._file.getLineBreakStyle();
var lines = this._file.getWhitespaceBefore(token).split(/\r\n|\r|\n/);

lines = callback(lines);
this._file.setWhitespaceBefore(token, lines.join(lineBreak));
};
TokenAssert.prototype._updateWhitespaceByLine = function(token, callback) {
var lineBreak = this._file.getLineBreakStyle();
var lines = this._file.getWhitespaceBefore(token).split(/\r\n|\r|\n/);
lines = callback(lines);
this._file.setWhitespaceBefore(token, lines.join(lineBreak));
};
/**
* Updates the whitespace of a line by passing split lines to a callback function
* for editing.
*
* @param {Object} token
* @param {Function} indentChar
* @param {Number} actual
* @param {Number} expected
*/
Function (anonymous_90)
✓ Was called
TokenAssert.prototype._updateCommentWhitespace = function(token, indentChar, actual, expected) {···
var difference = expected - actual;
var tokenLines = token.value.split(/\r\n|\r|\n/);
var i = 1;
if (difference >= 0) {
var lineWhitespace = (new Array(difference + 1)).join(indentChar);
for (; i < tokenLines.length; i++) {
tokenLines[i] = tokenLines[i] === '' ? '' : lineWhitespace + tokenLines[i];
}
} else {
for (; i < tokenLines.length; i++) {
tokenLines[i] = tokenLines[i].substring(-difference);
}
}

var newComment = new Token('CommentBlock', tokenLines.join(this._file.getLineBreakStyle()));
token.parentElement.replaceChild(newComment, token);
};
TokenAssert.prototype._updateCommentWhitespace = function(token, indentChar, actual, expected) {
var difference = expected - actual;
var tokenLines = token.value.split(/\r\n|\r|\n/);
var i = 1;
Branch IfStatement
✓ Positive was executed (if)
if (difference >= 0) {···
var lineWhitespace = (new Array(difference + 1)).join(indentChar);
for (; i < tokenLines.length; i++) {
tokenLines[i] = tokenLines[i] === '' ? '' : lineWhitespace + tokenLines[i];
}
} else {
✓ Negative was executed (else)
} else {···
for (; i < tokenLines.length; i++) {
tokenLines[i] = tokenLines[i].substring(-difference);
}
}
if (difference >= 0) {
var lineWhitespace = (new Array(difference + 1)).join(indentChar);
for (; i < tokenLines.length; i++) {
Branch ConditionalExpression
✗ Positive was not returned (? ...)
tokenLines[i] = tokenLines[i] === '' ? '' : lineWhitespace + tokenLines[i];
✓ Negative was returned (: ...)
tokenLines[i] = tokenLines[i] === '' ? '' : lineWhitespace + tokenLines[i];
tokenLines[i] = tokenLines[i] === '' ? '' : lineWhitespace + tokenLines[i];
}
} else {
for (; i < tokenLines.length; i++) {
tokenLines[i] = tokenLines[i].substring(-difference);
}
}
var newComment = new Token('CommentBlock', tokenLines.join(this._file.getLineBreakStyle()));
token.parentElement.replaceChild(newComment, token);
};
/**
* Requires tokens to be on the same line.
*
* @param {Object} options
* @param {Object} options.token
* @param {Object} options.nextToken
* @param {Boolean} [options.stickToPreviousToken]
* @param {String} [options.message]
* @return {Boolean} whether an error was found
*/
Function (anonymous_91)
✓ Was called
TokenAssert.prototype.sameLine = function(options) {···
options.exactly = 0;

return this.linesBetween(options);
};
TokenAssert.prototype.sameLine = function(options) {
options.exactly = 0;
return this.linesBetween(options);
};
/**
* Requires tokens to be on different lines.
*
* @param {Object} options
* @param {Object} options.token
* @param {Object} options.nextToken
* @param {Object} [options.message]
* @return {Boolean} whether an error was found
*/
Function (anonymous_92)
✓ Was called
TokenAssert.prototype.differentLine = function(options) {···
options.atLeast = 1;

return this.linesBetween(options);
};
TokenAssert.prototype.differentLine = function(options) {
options.atLeast = 1;
return this.linesBetween(options);
};
/**
* Requires tokens to have a certain amount of lines between them.
* Set at least one of atLeast or atMost OR set exactly.
*
* @param {Object} options
* @param {Object} options.token
* @param {Object} options.nextToken
* @param {Object} [options.message]
* @param {Object} [options.atLeast] At least how many lines the tokens are apart
* @param {Object} [options.atMost] At most how many lines the tokens are apart
* @param {Object} [options.exactly] Exactly how many lines the tokens are apart
* @param {Boolean} [options.stickToPreviousToken] When auto-fixing stick the
* nextToken onto the previous token.
* @return {Boolean} whether an error was found
*/
Function (anonymous_93)
✓ Was called
TokenAssert.prototype.linesBetween = function(options) {···
var token = options.token;
var nextToken = options.nextToken;
var atLeast = options.atLeast;
var atMost = options.atMost;
var exactly = options.exactly;

if (!token || !nextToken) {
return false;
}

this._validateOptions(options);

// Only attempt to remove or add lines if there are no comments between the two nodes
// as this prevents accidentally moving a valid token onto a line comment ed line
var fixed = !options.token.getNextNonWhitespaceToken().isComment;

var linesBetween = this._file.getLineCountBetween(token, nextToken);

var emitError = function(countPrefix, lineCount) {
var msgPrefix = token.value + ' and ' + nextToken.value;

var fix = function() {
this._augmentLineCount(options, lineCount);
}.bind(this);

if (!options.message) {
if (exactly === 0) {
// support sameLine
options.message = msgPrefix + ' should be on the same line';
} else if (atLeast === 1 && atMost === undefined) {
// support differentLine
options.message = msgPrefix + ' should be on different lines';
} else {
// support linesBetween
options.message = msgPrefix + ' should have ' + countPrefix + ' ' + lineCount + ' line(s) between them';
}
}

this.emit('error', {
message: options.message,
element: token,
offset: token.getSourceCodeLength(),
fix: fixed ? fix : undefined
});
}.bind(this);

if (atLeast !== undefined && linesBetween < atLeast) {
emitError('at least', atLeast);
return true;
}

if (atMost !== undefined && linesBetween > atMost) {
emitError('at most', atMost);
return true;
}

if (exactly !== undefined && linesBetween !== exactly) {
emitError('exactly', exactly);
return true;
}

return false;
};
TokenAssert.prototype.linesBetween = function(options) {
var token = options.token;
var nextToken = options.nextToken;
var atLeast = options.atLeast;
var atMost = options.atMost;
var exactly = options.exactly;
Branch IfStatement
✓ Positive was executed (if)
if (!token || !nextToken) {···
return false;
}
✓ Negative was executed (else)
}···

this._validateOptions(options);
Branch LogicalExpression
✓ Was returned
if (!token || !nextToken) {
✓ Was returned
if (!token || !nextToken) {
if (!token || !nextToken) {
return false;
}
this._validateOptions(options);
// Only attempt to remove or add lines if there are no comments between the two nodes
// as this prevents accidentally moving a valid token onto a line comment ed line
var fixed = !options.token.getNextNonWhitespaceToken().isComment;
var linesBetween = this._file.getLineCountBetween(token, nextToken);
Function (anonymous_94)
✓ Was called
var emitError = function(countPrefix, lineCount) {···
var msgPrefix = token.value + ' and ' + nextToken.value;

var fix = function() {
this._augmentLineCount(options, lineCount);
}.bind(this);

if (!options.message) {
if (exactly === 0) {
// support sameLine
options.message = msgPrefix + ' should be on the same line';
} else if (atLeast === 1 && atMost === undefined) {
// support differentLine
options.message = msgPrefix + ' should be on different lines';
} else {
// support linesBetween
options.message = msgPrefix + ' should have ' + countPrefix + ' ' + lineCount + ' line(s) between them';
}
}

this.emit('error', {
message: options.message,
element: token,
offset: token.getSourceCodeLength(),
fix: fixed ? fix : undefined
});
}.bind(this);
var emitError = function(countPrefix, lineCount) {
var msgPrefix = token.value + ' and ' + nextToken.value;
Function (anonymous_95)
✓ Was called
var fix = function() {···
this._augmentLineCount(options, lineCount);
}.bind(this);
var fix = function() {
this._augmentLineCount(options, lineCount);
}.bind(this);
Branch IfStatement
✓ Positive was executed (if)
if (!options.message) {···
if (exactly === 0) {
// support sameLine
options.message = msgPrefix + ' should be on the same line';
} else if (atLeast === 1 && atMost === undefined) {
// support differentLine
options.message = msgPrefix + ' should be on different lines';
} else {
// support linesBetween
options.message = msgPrefix + ' should have ' + countPrefix + ' ' + lineCount + ' line(s) between them';
}
}
✓ Negative was executed (else)
}···

this.emit('error', {
if (!options.message) {
Branch IfStatement
✓ Positive was executed (if)
if (exactly === 0) {···
// support sameLine
options.message = msgPrefix + ' should be on the same line';
} else if (atLeast === 1 && atMost === undefined) {
✓ Negative was executed (else)
} else if (atLeast === 1 && atMost === undefined) {···
// support differentLine
options.message = msgPrefix + ' should be on different lines';
} else {
// support linesBetween
options.message = msgPrefix + ' should have ' + countPrefix + ' ' + lineCount + ' line(s) between them';
}
if (exactly === 0) {
// support sameLine
options.message = msgPrefix + ' should be on the same line';
Branch IfStatement
✓ Positive was executed (if)
} else if (atLeast === 1 && atMost === undefined) {···
// support differentLine
options.message = msgPrefix + ' should be on different lines';
} else {
✓ Negative was executed (else)
} else {···
// support linesBetween
options.message = msgPrefix + ' should have ' + countPrefix + ' ' + lineCount + ' line(s) between them';
}
Branch LogicalExpression
✓ Was returned
} else if (atLeast === 1 && atMost === undefined) {
✓ Was returned
} else if (atLeast === 1 && atMost === undefined) {
} else if (atLeast === 1 && atMost === undefined) {
// support differentLine
options.message = msgPrefix + ' should be on different lines';
} else {
// support linesBetween
options.message = msgPrefix + ' should have ' + countPrefix + ' ' + lineCount + ' line(s) between them';
}
}
this.emit('error', {
message: options.message,
element: token,
offset: token.getSourceCodeLength(),
Branch ConditionalExpression
✓ Positive was returned (? ...)
fix: fixed ? fix : undefined
✓ Negative was returned (: ...)
fix: fixed ? fix : undefined
fix: fixed ? fix : undefined
});
}.bind(this);
Branch IfStatement
✓ Positive was executed (if)
if (atLeast !== undefined && linesBetween < atLeast) {···
emitError('at least', atLeast);
return true;
}
✓ Negative was executed (else)
}···

if (atMost !== undefined && linesBetween > atMost) {
Branch LogicalExpression
✓ Was returned
if (atLeast !== undefined && linesBetween < atLeast) {
✓ Was returned
if (atLeast !== undefined && linesBetween < atLeast) {
if (atLeast !== undefined && linesBetween < atLeast) {
emitError('at least', atLeast);
return true;
}
Branch IfStatement
✓ Positive was executed (if)
if (atMost !== undefined && linesBetween > atMost) {···
emitError('at most', atMost);
return true;
}
✓ Negative was executed (else)
}···

if (exactly !== undefined && linesBetween !== exactly) {
Branch LogicalExpression
✓ Was returned
if (atMost !== undefined && linesBetween > atMost) {
✓ Was returned
if (atMost !== undefined && linesBetween > atMost) {
if (atMost !== undefined && linesBetween > atMost) {
emitError('at most', atMost);
return true;
}
Branch IfStatement
✓ Positive was executed (if)
if (exactly !== undefined && linesBetween !== exactly) {···
emitError('exactly', exactly);
return true;
}
✓ Negative was executed (else)
}···

return false;
Branch LogicalExpression
✓ Was returned
if (exactly !== undefined && linesBetween !== exactly) {
✓ Was returned
if (exactly !== undefined && linesBetween !== exactly) {
if (exactly !== undefined && linesBetween !== exactly) {
emitError('exactly', exactly);
return true;
}
return false;
};
/**
* Throws errors if atLeast, atMost, and exactly options don't mix together properly or
* if the tokens provided are equivalent.
*
* @param {Object} options
* @param {Object} options.token
* @param {Object} options.nextToken
* @param {Object} [options.atLeast] At least how many spaces the tokens are apart
* @param {Object} [options.atMost] At most how many spaces the tokens are apart
* @param {Object} [options.exactly] Exactly how many spaces the tokens are apart
* @throws {Error} If the options are non-sensical
* @private
*/
Function (anonymous_96)
✓ Was called
TokenAssert.prototype._validateOptions = function(options) {···
var token = options.token;
var nextToken = options.nextToken;
var atLeast = options.atLeast;
var atMost = options.atMost;
var exactly = options.exactly;

if (token === nextToken) {
throw new Error('You cannot specify the same token as both token and nextToken');
}

if (atLeast === undefined &&
atMost === undefined &&
exactly === undefined) {
throw new Error('You must specify at least one option');
}

if (exactly !== undefined && (atLeast !== undefined || atMost !== undefined)) {
throw new Error('You cannot specify atLeast or atMost with exactly');
}

if (atLeast !== undefined && atMost !== undefined && atMost < atLeast) {
throw new Error('atLeast and atMost are in conflict');
}
};
TokenAssert.prototype._validateOptions = function(options) {
var token = options.token;
var nextToken = options.nextToken;
var atLeast = options.atLeast;
var atMost = options.atMost;
var exactly = options.exactly;
Branch IfStatement
✓ Positive was executed (if)
if (token === nextToken) {···
throw new Error('You cannot specify the same token as both token and nextToken');
}
✓ Negative was executed (else)
}···

if (atLeast === undefined &&
if (token === nextToken) {
throw new Error('You cannot specify the same token as both token and nextToken');
}
Branch IfStatement
✓ Positive was executed (if)
exactly === undefined) {···
throw new Error('You must specify at least one option');
}
✓ Negative was executed (else)
}···

if (exactly !== undefined && (atLeast !== undefined || atMost !== undefined)) {
Branch LogicalExpression
✓ Was returned
exactly === undefined) {
✓ Was returned
if (atLeast === undefined &&···
atMost === undefined &&
Branch LogicalExpression
✓ Was returned
atMost === undefined &&
✓ Was returned
if (atLeast === undefined &&
if (atLeast === undefined &&
atMost === undefined &&
exactly === undefined) {
throw new Error('You must specify at least one option');
}
Branch IfStatement
✓ Positive was executed (if)
if (exactly !== undefined && (atLeast !== undefined || atMost !== undefined)) {···
throw new Error('You cannot specify atLeast or atMost with exactly');
}
✓ Negative was executed (else)
}···

if (atLeast !== undefined && atMost !== undefined && atMost < atLeast) {
Branch LogicalExpression
✓ Was returned
if (exactly !== undefined && (atLeast !== undefined || atMost !== undefined)) {
✓ Was returned
if (exactly !== undefined && (atLeast !== undefined || atMost !== undefined)) {
Branch LogicalExpression
✓ Was returned
if (exactly !== undefined && (atLeast !== undefined || atMost !== undefined)) {
✓ Was returned
if (exactly !== undefined && (atLeast !== undefined || atMost !== undefined)) {
if (exactly !== undefined && (atLeast !== undefined || atMost !== undefined)) {
throw new Error('You cannot specify atLeast or atMost with exactly');
}
Branch IfStatement
✓ Positive was executed (if)
if (atLeast !== undefined && atMost !== undefined && atMost < atLeast) {···
throw new Error('atLeast and atMost are in conflict');
}
✓ Negative was executed (else)
}···
};
Branch LogicalExpression
✓ Was returned
if (atLeast !== undefined && atMost !== undefined && atMost < atLeast) {
✓ Was returned
if (atLeast !== undefined && atMost !== undefined && atMost < atLeast) {
Branch LogicalExpression
✓ Was returned
if (atLeast !== undefined && atMost !== undefined && atMost < atLeast) {
✓ Was returned
if (atLeast !== undefined && atMost !== undefined && atMost < atLeast) {
if (atLeast !== undefined && atMost !== undefined && atMost < atLeast) {
throw new Error('atLeast and atMost are in conflict');
}
};
/**
* Augments token whitespace to contain the correct number of newlines while preserving indentation
*
* @param {Object} options
* @param {Object} options.nextToken
* @param {Boolean} [options.stickToPreviousToken]
* @param {Number} lineCount
* @private
*/
Function (anonymous_97)
✓ Was called
TokenAssert.prototype._augmentLineCount = function(options, lineCount) {···
var token = options.nextToken;
if (lineCount === 0) {
if (options.stickToPreviousToken) {
var nextToken = this._file.getNextToken(token, {
includeComments: true
});
this._file.setWhitespaceBefore(nextToken, this._file.getWhitespaceBefore(token));
}

this._file.setWhitespaceBefore(token, ' ');
return;
}

this._updateWhitespaceByLine(token, function(lines) {
var currentLineCount = lines.length;
var lastLine = lines[lines.length - 1];

if (currentLineCount <= lineCount) {
// add additional lines that maintain the same indentation as the former last line
for (; currentLineCount <= lineCount; currentLineCount++) {
lines[lines.length - 1] = '';
lines.push(lastLine);
}
} else {
// remove lines and then ensure that the new last line maintains the previous indentation
lines = lines.slice(0, lineCount + 1);
lines[lines.length - 1] = lastLine;
}

return lines;
});
};
TokenAssert.prototype._augmentLineCount = function(options, lineCount) {
var token = options.nextToken;
Branch IfStatement
✓ Positive was executed (if)
if (lineCount === 0) {···
if (options.stickToPreviousToken) {
var nextToken = this._file.getNextToken(token, {
includeComments: true
});
this._file.setWhitespaceBefore(nextToken, this._file.getWhitespaceBefore(token));
}

this._file.setWhitespaceBefore(token, ' ');
return;
}
✓ Negative was executed (else)
}···

this._updateWhitespaceByLine(token, function(lines) {
if (lineCount === 0) {
Branch IfStatement
✓ Positive was executed (if)
if (options.stickToPreviousToken) {···
var nextToken = this._file.getNextToken(token, {
includeComments: true
});
this._file.setWhitespaceBefore(nextToken, this._file.getWhitespaceBefore(token));
}
✗ Negative was not executed (else)
}···

this._file.setWhitespaceBefore(token, ' ');
if (options.stickToPreviousToken) {
var nextToken = this._file.getNextToken(token, {
includeComments: true
});
this._file.setWhitespaceBefore(nextToken, this._file.getWhitespaceBefore(token));
}
this._file.setWhitespaceBefore(token, ' ');
return;
}
Function (anonymous_98)
✓ Was called
this._updateWhitespaceByLine(token, function(lines) {···
var currentLineCount = lines.length;
var lastLine = lines[lines.length - 1];

if (currentLineCount <= lineCount) {
// add additional lines that maintain the same indentation as the former last line
for (; currentLineCount <= lineCount; currentLineCount++) {
lines[lines.length - 1] = '';
lines.push(lastLine);
}
} else {
// remove lines and then ensure that the new last line maintains the previous indentation
lines = lines.slice(0, lineCount + 1);
lines[lines.length - 1] = lastLine;
}

return lines;
});
this._updateWhitespaceByLine(token, function(lines) {
var currentLineCount = lines.length;
var lastLine = lines[lines.length - 1];
Branch IfStatement
✓ Positive was executed (if)
if (currentLineCount <= lineCount) {···
// add additional lines that maintain the same indentation as the former last line
for (; currentLineCount <= lineCount; currentLineCount++) {
lines[lines.length - 1] = '';
lines.push(lastLine);
}
} else {
✓ Negative was executed (else)
} else {···
// remove lines and then ensure that the new last line maintains the previous indentation
lines = lines.slice(0, lineCount + 1);
lines[lines.length - 1] = lastLine;
}
if (currentLineCount <= lineCount) {
// add additional lines that maintain the same indentation as the former last line
for (; currentLineCount <= lineCount; currentLineCount++) {
lines[lines.length - 1] = '';
lines.push(lastLine);
}
} else {
// remove lines and then ensure that the new last line maintains the previous indentation
lines = lines.slice(0, lineCount + 1);
lines[lines.length - 1] = lastLine;
}
return lines;
});
};
module.exports = TokenAssert;
js-file.js
// var assert = require('assert');
var cst = require('cst');
var Parser = cst.Parser;
var Token = cst.Token;
var Program = cst.types.Program;
var Fragment = cst.Fragment;
var ScopesApi = cst.api.ScopesApi;
var treeIterator = require('./tree-iterator');
// var Program = cst.types.Program;
/**
* Operator list which are represented as keywords in token list.
*/
var KEYWORD_OPERATORS = {
'instanceof': true,
'in': true
};
/**
* File representation for JSCS.
*
* @name JsFile
* @param {Object} params
* @param {String} params.filename
* @param {String} params.source
* @param {Boolean} [params.es3]
*/
Function (anonymous_99)
✓ Was called
var JsFile = function(params) {···
params = params || {};
this._parseErrors = [];
this._filename = params.filename;
this._source = params.source;

this._es3 = params.es3 || false;

this._lineBreaks = null;
this._lines = this._source.split(/\r\n|\r|\n/);

var parser = new Parser({
strictMode: false,
languageExtensions: {
gritDirectives: true,
appleInstrumentationDirectives: true
}
});

try {
this._program = parser.parse(this._source);
} catch (e) {
this._parseErrors.push(e);
this._program = new Program([
new Token('EOF', '')
]);
}

// Lazy initialization
this._scopes = null;
};
var JsFile = function(params) {
Branch LogicalExpression
✗ Was not returned
params = params || {};
✓ Was returned
params = params || {};
params = params || {};
this._parseErrors = [];
this._filename = params.filename;
this._source = params.source;
Branch LogicalExpression
✓ Was returned
this._es3 = params.es3 || false;
✓ Was returned
this._es3 = params.es3 || false;
this._es3 = params.es3 || false;
this._lineBreaks = null;
this._lines = this._source.split(/\r\n|\r|\n/);
var parser = new Parser({
strictMode: false,
languageExtensions: {
gritDirectives: true,
appleInstrumentationDirectives: true
}
});
try {
this._program = parser.parse(this._source);
} catch (e) {
this._parseErrors.push(e);
this._program = new Program([
new Token('EOF', '')
]);
}
// Lazy initialization
this._scopes = null;
};
JsFile.prototype = {
/**
* @returns {cst.types.Program}
*/
Function (anonymous_100)
✗ Was not called
getProgram: function() {···
return this._program;
},
getProgram: function() {
return this._program;
},
/**
* Returns the first line break character encountered in the file.
* Assumes LF if the file is only one line.
*
* @returns {String}
*/
Function (anonymous_101)
✓ Was called
getLineBreakStyle: function() {···
var lineBreaks = this.getLineBreaks();
return lineBreaks.length ? lineBreaks[0] : '\n';
},
getLineBreakStyle: function() {
var lineBreaks = this.getLineBreaks();
Branch ConditionalExpression
✓ Positive was returned (? ...)
return lineBreaks.length ? lineBreaks[0] : '\n';
✓ Negative was returned (: ...)
return lineBreaks.length ? lineBreaks[0] : '\n';
return lineBreaks.length ? lineBreaks[0] : '\n';
},
/**
* Returns all line break characters from the file.
*
* @returns {String[]}
*/
Function (anonymous_102)
✓ Was called
getLineBreaks: function() {···
if (this._lineBreaks === null) {
this._lineBreaks = this._source.match(/\r\n|\r|\n/g) || [];
}
return this._lineBreaks;
},
getLineBreaks: function() {
Branch IfStatement
✓ Positive was executed (if)
if (this._lineBreaks === null) {···
this._lineBreaks = this._source.match(/\r\n|\r|\n/g) || [];
}
✓ Negative was executed (else)
}···
return this._lineBreaks;
if (this._lineBreaks === null) {
Branch LogicalExpression
✓ Was returned
this._lineBreaks = this._source.match(/\r\n|\r|\n/g) || [];
✓ Was returned
this._lineBreaks = this._source.match(/\r\n|\r|\n/g) || [];
this._lineBreaks = this._source.match(/\r\n|\r|\n/g) || [];
}
return this._lineBreaks;
},
/**
* Sets whitespace before specified token.
*
* @param {Object} token - in front of which we will add/remove/replace the whitespace token
* @param {String} whitespace - value of the whitespace token - `\n`, `\s`, `\t`
*/
Function (anonymous_103)
✓ Was called
setWhitespaceBefore: function(token, whitespace) {···
var prevToken = token.getPreviousToken();
var ws = new Token('Whitespace', whitespace);
var fragment = new Fragment(ws);

if (prevToken && prevToken.isWhitespace) {
if (whitespace === '') {
prevToken.remove();
return;
}

prevToken.parentElement.replaceChild(fragment, prevToken);
return;
}

this._setTokenBefore(token, fragment);
},
setWhitespaceBefore: function(token, whitespace) {
var prevToken = token.getPreviousToken();
var ws = new Token('Whitespace', whitespace);
var fragment = new Fragment(ws);
Branch IfStatement
✓ Positive was executed (if)
if (prevToken && prevToken.isWhitespace) {···
if (whitespace === '') {
prevToken.remove();
return;
}

prevToken.parentElement.replaceChild(fragment, prevToken);
return;
}
✓ Negative was executed (else)
}···

this._setTokenBefore(token, fragment);
Branch LogicalExpression
✓ Was returned
if (prevToken && prevToken.isWhitespace) {
✓ Was returned
if (prevToken && prevToken.isWhitespace) {
if (prevToken && prevToken.isWhitespace) {
Branch IfStatement
✓ Positive was executed (if)
if (whitespace === '') {···
prevToken.remove();
return;
}
✓ Negative was executed (else)
}···

prevToken.parentElement.replaceChild(fragment, prevToken);
if (whitespace === '') {
prevToken.remove();
return;
}
prevToken.parentElement.replaceChild(fragment, prevToken);
return;
}
this._setTokenBefore(token, fragment);
},
Function (anonymous_104)
✓ Was called
_setTokenBefore: function(token, fragment) {···
var parent = token;
var grandpa = parent.parentElement;

while (grandpa) {
try {
grandpa.insertChildBefore(fragment, parent);
break;
} catch (e) {}

parent = grandpa;
grandpa = parent.parentElement;
}
},
_setTokenBefore: function(token, fragment) {
var parent = token;
var grandpa = parent.parentElement;
while (grandpa) {
try {
grandpa.insertChildBefore(fragment, parent);
break;
} catch (e) {}
parent = grandpa;
grandpa = parent.parentElement;
}
},
/**
* Returns whitespace before specified token.
*
* @param {Object} token
* @returns {String}
*/
Function (anonymous_105)
✓ Was called
getWhitespaceBefore: function(token) {···
if (!token.getPreviousToken) {
console.log(token);
}
var prev = token.getPreviousToken();

if (prev && prev.isWhitespace) {
return prev.getSourceCode();
}

return '';
},
getWhitespaceBefore: function(token) {
Branch IfStatement
✗ Positive was not executed (if)
if (!token.getPreviousToken) {···
console.log(token);
}
✓ Negative was executed (else)
}···
var prev = token.getPreviousToken();
if (!token.getPreviousToken) {
console.log(token);
}
var prev = token.getPreviousToken();
Branch IfStatement
✓ Positive was executed (if)
if (prev && prev.isWhitespace) {···
return prev.getSourceCode();
}
✓ Negative was executed (else)
}···

return '';
Branch LogicalExpression
✓ Was returned
if (prev && prev.isWhitespace) {
✓ Was returned
if (prev && prev.isWhitespace) {
if (prev && prev.isWhitespace) {
return prev.getSourceCode();
}
return '';
},
/**
* Returns the first token for the node from the AST.
*
* @param {Object} node
* @returns {Object}
*/
Function (anonymous_106)
✓ Was called
getFirstNodeToken: function(node) {···
return node.getFirstToken();
},
getFirstNodeToken: function(node) {
return node.getFirstToken();
},
/**
* Returns the last token for the node from the AST.
*
* @param {Object} node
* @returns {Object}
*/
Function (anonymous_107)
✓ Was called
getLastNodeToken: function(node) {···
return node.getLastToken();
},
getLastNodeToken: function(node) {
return node.getLastToken();
},
/**
* Returns the first token for the file.
*
* @param {Option} [options]
* @param {Boolean} [options.includeComments=false]
* @param {Boolean} [options.includeWhitespace=false]
* @returns {Object}
*/
Function (anonymous_108)
✓ Was called
getFirstToken: function(/*options*/) {···
return this._program.getFirstToken();
},
getFirstToken: function(/*options*/) {
return this._program.getFirstToken();
},
/**
* Returns the last token for the file.
*
* @param {Option} [options]
* @param {Boolean} [options.includeComments=false]
* @param {Boolean} [options.includeWhitespace=false]
* @returns {Object}
*/
Function (anonymous_109)
✓ Was called
getLastToken: function(/*options*/) {···
return this._program.getLastToken();
},
getLastToken: function(/*options*/) {
return this._program.getLastToken();
},
/**
* Returns the first token before the given.
*
* @param {Object} token
* @param {Object} [options]
* @param {Boolean} [options.includeComments=false]
* @returns {Object|undefined}
*/
Function (anonymous_110)
✓ Was called
getPrevToken: function(token, options) {···
if (options && options.includeComments) {
return token.getPreviousNonWhitespaceToken();
}

return token.getPreviousCodeToken();
},
getPrevToken: function(token, options) {
Branch IfStatement
✓ Positive was executed (if)
if (options && options.includeComments) {···
return token.getPreviousNonWhitespaceToken();
}
✓ Negative was executed (else)
}···

return token.getPreviousCodeToken();
Branch LogicalExpression
✓ Was returned
if (options && options.includeComments) {
✓ Was returned
if (options && options.includeComments) {
if (options && options.includeComments) {
return token.getPreviousNonWhitespaceToken();
}
return token.getPreviousCodeToken();
},
/**
* Returns the first token after the given.
*
* @param {Object} token
* @param {Object} [options]
* @param {Boolean} [options.includeComments=false]
* @returns {Object|undefined}
*/
Function (anonymous_111)
✓ Was called
getNextToken: function(token, options) {···
if (options && options.includeComments) {
return token.getNextNonWhitespaceToken();
} else {
return token.getNextCodeToken();
}
},
getNextToken: function(token, options) {
Branch IfStatement
✓ Positive was executed (if)
if (options && options.includeComments) {···
return token.getNextNonWhitespaceToken();
} else {
✓ Negative was executed (else)
} else {···
return token.getNextCodeToken();
}
Branch LogicalExpression
✓ Was returned
if (options && options.includeComments) {
✓ Was returned
if (options && options.includeComments) {
if (options && options.includeComments) {
return token.getNextNonWhitespaceToken();
} else {
return token.getNextCodeToken();
}
},
/**
* Returns the first token before the given which matches type (and value).
*
* @param {Object} token
* @param {String} type
* @param {String} [value]
* @returns {Object|null}
*/
Function (anonymous_112)
✓ Was called
findPrevToken: function(token, type, value) {···
var prevToken = this.getPrevToken(token);
while (prevToken) {
if (prevToken.type === type && (value === undefined || prevToken.value === value)) {
return prevToken;
}

prevToken = this.getPrevToken(prevToken);
}
return prevToken;
},
findPrevToken: function(token, type, value) {
var prevToken = this.getPrevToken(token);
while (prevToken) {
Branch IfStatement
✓ Positive was executed (if)
if (prevToken.type === type && (value === undefined || prevToken.value === value)) {···
return prevToken;
}
✓ Negative was executed (else)
}···

prevToken = this.getPrevToken(prevToken);
Branch LogicalExpression
✓ Was returned
if (prevToken.type === type && (value === undefined || prevToken.value === value)) {
✓ Was returned
if (prevToken.type === type && (value === undefined || prevToken.value === value)) {
Branch LogicalExpression
✓ Was returned
if (prevToken.type === type && (value === undefined || prevToken.value === value)) {
✓ Was returned
if (prevToken.type === type && (value === undefined || prevToken.value === value)) {
if (prevToken.type === type && (value === undefined || prevToken.value === value)) {
return prevToken;
}
prevToken = this.getPrevToken(prevToken);
}
return prevToken;
},
/**
* Returns the first token after the given which matches type (and value).
*
* @param {Object} token
* @param {String} type
* @param {String} [value]
* @returns {Object|null}
*/
Function (anonymous_113)
✓ Was called
findNextToken: function(token, type, value) {···
var nextToken = token.getNextToken();

while (nextToken) {
if (nextToken.type === type && (value === undefined || nextToken.value === value)) {
return nextToken;
}

nextToken = nextToken.getNextToken();
}
return nextToken;
},
findNextToken: function(token, type, value) {
var nextToken = token.getNextToken();
while (nextToken) {
Branch IfStatement
✓ Positive was executed (if)
if (nextToken.type === type && (value === undefined || nextToken.value === value)) {···
return nextToken;
}
✓ Negative was executed (else)
}···

nextToken = nextToken.getNextToken();
Branch LogicalExpression
✓ Was returned
if (nextToken.type === type && (value === undefined || nextToken.value === value)) {
✓ Was returned
if (nextToken.type === type && (value === undefined || nextToken.value === value)) {
Branch LogicalExpression
✓ Was returned
if (nextToken.type === type && (value === undefined || nextToken.value === value)) {
✓ Was returned
if (nextToken.type === type && (value === undefined || nextToken.value === value)) {
if (nextToken.type === type && (value === undefined || nextToken.value === value)) {
return nextToken;
}
nextToken = nextToken.getNextToken();
}
return nextToken;
},
/**
* Returns the first token before the given which matches type (and value).
*
* @param {Object} token
* @param {String} value
* @returns {Object|null}
*/
Function (anonymous_114)
✓ Was called
findPrevOperatorToken: function(token, value) {···
return this.findPrevToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
},
findPrevOperatorToken: function(token, value) {
Branch ConditionalExpression
✓ Positive was returned (? ...)
return this.findPrevToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
✓ Negative was returned (: ...)
return this.findPrevToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
return this.findPrevToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
},
/**
* Returns the first token after the given which matches type (and value).
*
* @param {Object} token
* @param {String} value
* @returns {Object|null}
*/
Function (anonymous_115)
✓ Was called
findNextOperatorToken: function(token, value) {···
return this.findNextToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
},
findNextOperatorToken: function(token, value) {
Branch ConditionalExpression
✓ Positive was returned (? ...)
return this.findNextToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
✓ Negative was returned (: ...)
return this.findNextToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
return this.findNextToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
},
/**
* Iterates through the token tree using tree iterator.
* Calls passed function for every token.
*
* @param {Function} cb
* @param {Object} [tree]
*/
Function (anonymous_116)
✓ Was called
iterate: function(cb, tree) {···
return treeIterator.iterate(tree || this._program, cb);
},
iterate: function(cb, tree) {
Branch LogicalExpression
✓ Was returned
return treeIterator.iterate(tree || this._program, cb);
✓ Was returned
return treeIterator.iterate(tree || this._program, cb);
return treeIterator.iterate(tree || this._program, cb);
},
/**
* Returns nodes by type(s) from earlier built index.
*
* @param {String|String[]} type
* @returns {Object[]}
*/
Function (anonymous_117)
✓ Was called
getNodesByType: function(type) {···
type = Array.isArray(type) ? type : [type];
var result = [];

for (var i = 0, l = type.length; i < l; i++) {
var nodes = this._program.selectNodesByType(type[i]);

if (nodes) {
result = result.concat(nodes);
}
}

return result;
},
getNodesByType: function(type) {
Branch ConditionalExpression
✓ Positive was returned (? ...)
type = Array.isArray(type) ? type : [type];
✓ Negative was returned (: ...)
type = Array.isArray(type) ? type : [type];
type = Array.isArray(type) ? type : [type];
var result = [];
for (var i = 0, l = type.length; i < l; i++) {
var nodes = this._program.selectNodesByType(type[i]);
Branch IfStatement
✓ Positive was executed (if)
if (nodes) {···
result = result.concat(nodes);
}
✗ Negative was not executed (else)
}···
}
if (nodes) {
result = result.concat(nodes);
}
}
return result;
},
/**
* Iterates nodes by type(s) from earlier built index.
* Calls passed function for every matched node.
*
* @param {String|String[]} type
* @param {Function} cb
* @param {Object} context
*/
Function (anonymous_118)
✓ Was called
iterateNodesByType: function(type, cb, context) {···
return this.getNodesByType(type).forEach(cb, context || this);
},
iterateNodesByType: function(type, cb, context) {
Branch LogicalExpression
✓ Was returned
return this.getNodesByType(type).forEach(cb, context || this);
✗ Was not returned
return this.getNodesByType(type).forEach(cb, context || this);
return this.getNodesByType(type).forEach(cb, context || this);
},
/**
* Iterates tokens by type(s) from the token array.
* Calls passed function for every matched token.
*
* @param {String|String[]} type
* @param {Function} cb
*/
Function (anonymous_119)
✓ Was called
iterateTokensByType: function(type, cb) {···
var tokens;

if (Array.isArray(type)) {
tokens = [];
for (var i = 0; i < type.length; i++) {
var items = this._program.selectTokensByType(type[i]);
tokens = tokens.concat(items);
}
} else {
tokens = this._program.selectTokensByType(type);
}

tokens.forEach(cb);
},
iterateTokensByType: function(type, cb) {
var tokens;
Branch IfStatement
✓ Positive was executed (if)
if (Array.isArray(type)) {···
tokens = [];
for (var i = 0; i < type.length; i++) {
var items = this._program.selectTokensByType(type[i]);
tokens = tokens.concat(items);
}
} else {
✓ Negative was executed (else)
} else {···
tokens = this._program.selectTokensByType(type);
}
if (Array.isArray(type)) {
tokens = [];
for (var i = 0; i < type.length; i++) {
var items = this._program.selectTokensByType(type[i]);
tokens = tokens.concat(items);
}
} else {
tokens = this._program.selectTokensByType(type);
}
tokens.forEach(cb);
},
/**
* Iterates tokens by type and value(s) from the token array.
* Calls passed function for every matched token.
*
* @param {String} type
* @param {String|String[]} value
* @param {Function} cb
*/
Function (anonymous_120)
✓ Was called
iterateTokensByTypeAndValue: function(type, value, cb) {···
var values = (typeof value === 'string') ? [value] : value;
var valueIndex = {};
values.forEach(function(type) {
valueIndex[type] = true;
});

this.iterateTokensByType(type, function(token) {
if (valueIndex[token.value]) {
cb(token);
}
});
},
iterateTokensByTypeAndValue: function(type, value, cb) {