Skip to content

Commit 6cf5340

Browse files
author
Raghav Dua
authored
Merge pull request #228 from pinkiebell/bounty
Feature: run solium cli without config files
2 parents 96a6530 + 3207285 commit 6cf5340

File tree

2 files changed

+87
-32
lines changed

2 files changed

+87
-32
lines changed

docs/user-guide.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,16 @@ Use ``solium --help`` for more information on usage.
7373
``-d`` can be used in place of ``--dir`` and ``-f`` in place of ``--file``.
7474

7575

76-
After linting over your code, Solium produces either warnings, errors or both. The app exits with a non-zero code ONLY if 1 or more errors were found.
77-
So if all you got was warnings, solium exits with code ``0``.
76+
You can specify rules or plugins to apply as commandline options. If you specify one, it overrides its corresponding configuration in the soliumrc file.
77+
78+
``solium --plugin zeppelin --rule 'indentation: ["error", 4]' -d contracts/``
79+
80+
Use ``--no-soliumrc`` and ``--no-soliumignore`` if you want to run solium in any arbitrary folder without looking for the config files.
81+
82+
``solium --no-soliumrc --no-soliumignore --plugin zeppelin --rule 'indentation: ["error", 4]' -f contract.sol``
83+
84+
After linting over your code, Solium produces either warnings, errors or both. The tool exits with a non-zero code only if 1 or more errors were found.
85+
So if all you got was warnings, solium exits with ``0``.
7886

7987
Whether an issue should be flagged as an error or warning by its rule is configurable through ``.soliumrc.json``.
8088

lib/cli.js

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,11 @@ function lint(userConfig, input, ignore, errorReporter) {
203203
* @param {Object} cliObject Commander Object handling the cli
204204
*/
205205
function createCliOptions(cliObject) {
206+
function collect(val, memo) {
207+
memo.push(val);
208+
return memo;
209+
}
210+
206211
cliObject
207212
.version(`Solium version ${version}`)
208213
.description("Linter to find & fix style and security issues in Solidity smart contracts.")
@@ -217,7 +222,21 @@ function createCliOptions(cliObject) {
217222
.option("--fix", "Fix Lint issues where possible")
218223
.option("--debug", "Display debug information")
219224
.option("--watch", "Watch for file changes")
220-
.option("--hot", "(Deprecated) Same as --watch");
225+
.option("--hot", "(Deprecated) Same as --watch")
226+
.option("--no-soliumignore", "Do not look for .soliumignore file")
227+
.option("--no-soliumrc", "Do not look for soliumrc configuration file")
228+
.option(
229+
"--rule [rule]",
230+
"Rule to execute. This overrides the specified rule's configuration in soliumrc if present",
231+
collect,
232+
[]
233+
)
234+
.option(
235+
"--plugin [plugin]",
236+
"Plugin to execute. This overrides the specified plugin's configuration in soliumrc if present",
237+
collect,
238+
[]
239+
);
221240
}
222241

223242
/**
@@ -243,7 +262,7 @@ function getErrorReporter(name) {
243262
*/
244263
function execute(programArgs) {
245264

246-
let userConfig, ignore, errorReporter;
265+
let userConfig = {}, ignore, errorReporter;
247266

248267
createCliOptions(cli);
249268
programArgs.length === 2 ? cli.help() : cli.parse(programArgs);
@@ -259,31 +278,33 @@ function execute(programArgs) {
259278
process.exit(errorCodes.INVALID_PARAMS);
260279
}
261280

262-
/**
263-
* If cli.config option is NOT specified, then resort to .soliumrc in current dir.
264-
* Else,
265-
* If path is absolute, assign as-it-is.
266-
* Else (relative pathing) join path with current dir.
267-
*/
268-
const soliumrcAbsPath = cli.config ?
269-
(path.isAbsolute(cli.config) ? cli.config : path.join(CWD, cli.config)) :
270-
SOLIUMRC_FILENAME_ABSOLUTE;
271-
272-
try {
273-
userConfig = require(soliumrcAbsPath);
274-
} catch (e) {
275-
// Check if soliumrc file exists. If yes, then the file is in an invalid format.
276-
if (fs.existsSync(soliumrcAbsPath)) {
277-
errorReporter.reportFatal(`An invalid ${SOLIUMRC_FILENAME} was provided. ${e.message}`);
278-
} else {
279-
if (cli.config) {
280-
errorReporter.reportFatal(`${soliumrcAbsPath} does not exist.`);
281+
if (cli.soliumrc) {
282+
/**
283+
* If cli.config option is NOT specified, then resort to .soliumrc in current dir.
284+
* Else,
285+
* If path is absolute, assign as-it-is.
286+
* Else (relative pathing) join path with current dir.
287+
*/
288+
const soliumrcAbsPath = cli.config ?
289+
(path.isAbsolute(cli.config) ? cli.config : path.join(CWD, cli.config)) :
290+
SOLIUMRC_FILENAME_ABSOLUTE;
291+
292+
try {
293+
userConfig = require(soliumrcAbsPath);
294+
} catch (e) {
295+
// Check if soliumrc file exists. If yes, then the file is in an invalid format.
296+
if (fs.existsSync(soliumrcAbsPath)) {
297+
errorReporter.reportFatal(`An invalid ${SOLIUMRC_FILENAME} was provided. ${e.message}`);
281298
} else {
282-
errorReporter.reportFatal(`Couldn't find ${SOLIUMRC_FILENAME} in the current directory.`);
299+
if (cli.config) {
300+
errorReporter.reportFatal(`${soliumrcAbsPath} does not exist.`);
301+
} else {
302+
errorReporter.reportFatal(`Couldn't find ${SOLIUMRC_FILENAME} in the current directory.`);
303+
}
283304
}
284-
}
285305

286-
process.exit(errorCodes.NO_SOLIUMRC);
306+
process.exit(errorCodes.NO_SOLIUMRC);
307+
}
287308
}
288309

289310
//if custom rules' file is set, make sure we have its absolute path
@@ -302,13 +323,39 @@ function execute(programArgs) {
302323
debug: Boolean(cli.debug)
303324
};
304325

326+
userConfig.plugins = userConfig.plugins || [];
327+
userConfig.rules = userConfig.rules || {};
328+
329+
for (const plugin of cli.plugin) {
330+
userConfig.plugins.push(plugin);
331+
}
332+
333+
for (const rule of cli.rule) {
334+
// If no ":" was found, it means only the rule's name was specified.
335+
// Treat it as an error and adopt its default configuration options.
336+
if (!rule.includes(":")) {
337+
userConfig.rules[rule] = "error";
338+
continue;
339+
}
340+
341+
let [key, value] = rule.split(":").map(i => i.trim());
342+
try {
343+
value = JSON.parse(value);
344+
} catch (e) {
345+
errorReporter.reportFatal(`There was an error trying to parse '${rule}': ${e.message}`);
346+
process.exit(errorCodes.INVALID_PARAMS);
347+
}
348+
userConfig.rules[key] = value;
349+
}
350+
305351
//get all files & folders to ignore from .soliumignore
306-
try {
307-
ignore = fs.readFileSync(SOLIUMIGNORE_FILENAME_ABSOLUTE, "utf8").split("\n");
308-
} catch (e) {
309-
errorReporter.reportInternal(
310-
`There was an error trying to read '${SOLIUMIGNORE_FILENAME_ABSOLUTE}': ${e.message}`
311-
);
352+
if (cli.soliumignore) {
353+
try {
354+
ignore = fs.readFileSync(SOLIUMIGNORE_FILENAME_ABSOLUTE, "utf8").split("\n");
355+
} catch (e) {
356+
errorReporter.reportInternal(
357+
`There was an error trying to read '${SOLIUMIGNORE_FILENAME_ABSOLUTE}': ${e.message}`);
358+
}
312359
}
313360

314361
if (cli.hot) {

0 commit comments

Comments
 (0)