Skip to content

Commit

Permalink
Add cli option: --max-warnings (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
duaraghav8 committed Feb 2, 2019
1 parent 3b95a04 commit aa5d2f0
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 23 deletions.
96 changes: 74 additions & 22 deletions lib/cli.js
Expand Up @@ -13,7 +13,6 @@ let cli = require("commander"),
chokidar = require("chokidar"),
traverse = require("sol-digger"),
solium = require("./solium"),
sum = require("lodash/sum"),
version = require("../package.json").version;

let CWD = process.cwd(),
Expand All @@ -24,7 +23,14 @@ let CWD = process.cwd(),
DEFAULT_SOLIUMIGNORE_PATH = `${__dirname}/cli-utils/.default-solium-ignore`,
DEFAULT_SOLIUMRC_PATH = `${__dirname}/cli-utils/.default-soliumrc.json`;

let errorCodes = { ERRORS_FOUND: 1, NO_SOLIUMRC: 3, WRITE_FAILED: 4, INVALID_PARAMS: 5, FILE_NOT_FOUND: 6 };
let errorCodes = {
ERRORS_FOUND: 1,
NO_SOLIUMRC: 3,
WRITE_FAILED: 4,
INVALID_PARAMS: 5,
FILE_NOT_FOUND: 6,
WARNING_THRESHOLD_EXCEEDED: 7
};

/**
* Create default configuration files in the user's directory
Expand Down Expand Up @@ -78,16 +84,35 @@ function createDefaultConfigJSON() {
writeConfigFile(require(DEFAULT_SOLIUMRC_PATH));
}

/**
* Count the number of errors and warnings
* @param {Array} issues Array of ethlint issue objects
* @returns {Integer, Integer} Total number of errors and warnings present in issues
*/
function countErrWarn(issues) {
let e = 0, w = 0;

issues.forEach(i => {
if (i.type === "error") {
e++;
} else if (i.type === "warning") {
w++;
}
});

return { w, e };
}

/**
* Lint a source code string based on user settings. If autofix is enabled, write the fixed code back to file.
* @param {String} sourceCode The source code to be linted
* @param {Object} userConfig User configuration
* @param {Object} errorReporter The error reporter to use
* @param {String} fileName (optional) File name to use when reporting errors
* @returns {Integer} numOfErrors Number of Lint ERRORS that occured.
* @returns {Integer, Integer} Total number of errors and warnings found
*/
function lintString(sourceCode, userConfig, errorReporter, fileName) {
let lintErrors, fixesApplied;
let lintErrors, fixesApplied, additionalErrors = [];

try {
if (userConfig.options.autofix || userConfig.options.autofixDryrun) {
Expand All @@ -98,6 +123,10 @@ function lintString(sourceCode, userConfig, errorReporter, fileName) {
applyFixes(fileName, result);
fixesApplied = result.fixesApplied;
} else {
// When using only fix dry run, the warnings that were fixed
// must also be counted in totalWarnings. See issue #255.
additionalErrors = result.fixesApplied;

errorReporter.reportDiff(fileName,
sourceCode, result.fixedSourceCode, result.fixesApplied.length);
}
Expand Down Expand Up @@ -125,9 +154,11 @@ function lintString(sourceCode, userConfig, errorReporter, fileName) {
lintErrors.length &&
errorReporter.report(fileName, sourceCode, lintErrors, fixesApplied);

return lintErrors.reduce(function(numOfErrors, err) {
return err.type === "error" ? numOfErrors+1 : numOfErrors;
}, 0);
const { e, w } = countErrWarn(lintErrors),
{ w: aw } = countErrWarn(additionalErrors);

// TODO: fix issue #258
return { errorCount: e, warningCount: w+aw };
}

function applyFixes(fileName, lintResult) {
Expand All @@ -139,7 +170,7 @@ function applyFixes(fileName, lintResult) {
* @param {String} fileName The path to the file to be linted
* @param {Object} userConfig User configuration
* @param {Object} errorReporter The error reporter to use
* @returns {Integer} numOfErrors Number of Lint ERRORS that occured (the result returned by lintString())
* @returns {Integer, Integer} Total number of errors and warnings found
*/
function lintFile(fileName, userConfig, errorReporter) {
let sourceCode;
Expand All @@ -155,14 +186,14 @@ function lintFile(fileName, userConfig, errorReporter) {
}

/**
* Function that calls Solium object's linter based on user settings.
* If not given, we lint the entire directory's (and sub-directories') solidity files.
* Function that calls Solium object's linter based on user settings
* If not given, we lint the entire directory's (and sub-directories') solidity files
* @param {Object} userConfig User's configurations that contain information about which linting rules to apply
* @param {String} filename (optional) The single file to be linted.
* @returns {Integer} totalNumOfErrors Total no. of errors found throughout the codebase (directory) linted.
* @param {String} filename (optional) The single file to be linted
* @returns {Integer, Integer} Total number of errors and warnings found
*/
function lint(userConfig, input, ignore, errorReporter) {
let filesToLint, errorCount;
let filesToLint, errorCount = 0, warningCount = 0;

//If filename is provided, lint it. Otherwise, lint over current directory & sub-directories
if (input.file) {
Expand All @@ -185,23 +216,32 @@ function lint(userConfig, input, ignore, errorReporter) {
}

if (filesToLint) {
errorCount = sum(filesToLint.map(function(file, index) {
userConfig.options.returnInternalIssues = (index === 0);
return lintFile(file, userConfig, errorReporter);
}));
filesToLint.forEach((file, i) => {
// Avoid repeatedly reporting internal issues.
// Only report them once, during linting of the first file.
userConfig.options.returnInternalIssues = (i === 0);
const { errorCount: e, warningCount: w } = lintFile(file, userConfig, errorReporter);

errorCount += e;
warningCount += w;
});
} else if (input.stdin) {
// This only works on *nix. Need to fix to enable stdin input in windows.
// This only works on unix.
// TODO: Need to fix this to enable stdin input in windows.
let sourceCode = fs.readFileSync("/dev/stdin", "utf-8");

userConfig.options.returnInternalIssues = true;
errorCount = lintString(sourceCode, userConfig, errorReporter, "[stdin]");
const { errorCount: e, warningCount: w } = lintString(sourceCode, userConfig, errorReporter, "[stdin]");

errorCount = e;
warningCount = w;
} else {
errorReporter.reportFatal("Must specify input for linter using --file, --dir or --stdin");
errorReporter.reportFatal("Must specify input for linter (either file, directory or stdin)");
process.exit(errorCodes.INVALID_PARAMS);
}

errorReporter.finalize && errorReporter.finalize();
return errorCount;
return { errorCount, warningCount };
}

/**
Expand All @@ -224,6 +264,7 @@ function createCliOptions(cliObject) {
.option("-d, --dir [dirpath::String]", "Directory containing Solidity files to lint")
.option("-R, --reporter [name::String]", "Format to report lint issues in (pretty | gcc)", "pretty")
.option("-c, --config [filepath::String]", "Path to the .soliumrc configuration file")
.option("-w, --max-warnings [count::Integer]", "Maximum number of warnings tolerable", -1)
.option("-, --stdin", "Read input file from stdin")
.option("--fix", "Fix Lint issues where possible")
.option("--fix-dry-run", "Output fix diff without applying it")
Expand Down Expand Up @@ -392,7 +433,16 @@ function execute(programArgs) {
}
}

let errorCount = lint(userConfig, { file: cli.file, dir: cli.dir, stdin: cli.stdin }, ignore, errorReporter);
let { errorCount, warningCount } = lint(
userConfig,
{
file: cli.file,
dir: cli.dir,
stdin: cli.stdin
},
ignore,
errorReporter
);

if (cli.watch) {

Expand All @@ -407,6 +457,8 @@ function execute(programArgs) {

} else if (errorCount > 0) {
process.exit(errorCodes.ERRORS_FOUND);
} else if (cli.maxWarnings > -1 && warningCount > cli.maxWarnings) {
process.exit(errorCodes.WARNING_THRESHOLD_EXCEEDED);
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/reporters/pretty.js
Expand Up @@ -43,7 +43,7 @@ module.exports = {
},

report(filename, sourceCode, lintErrors, fixesApplied) {
// Remove internal issue, so only rule errors reach the next loop
// Remove internal issues, so only rule errors reach the next loop
lintErrors.forEach((issue, index) => {
if (!issue.internal) {
return;
Expand Down

0 comments on commit aa5d2f0

Please sign in to comment.