Comparing version 1.0.15 to 1.1.0
@@ -123,2 +123,3 @@ ## Solhint Project | ||
| **no-simple-event-func-name** | Event and function names must be different | | ||
| **avoid-tx-origin** | Avoid to use tx.origin | | ||
@@ -150,5 +151,23 @@ ### Style Guide Codes: | ||
| **max-line-length** | Line length must be no more than 120 but current length is 121. | | ||
| **payable-fallback** | When fallback is not payable you will not be able to receive ethers | | ||
| **no-empty-blocks** | Code contains empty block | | ||
| **no-unused-vars** | Variable "name" is unused | | ||
| **function-max-lines** | Function body contains "count" lines but allowed no more than "maxLines" lines | | ||
| **space-after-comma** | Comma must be separated from next element by space | | ||
| **no-spaces-before-semicolon**| Semicolon must not have spaces before | | ||
### Best Practise Codes: | ||
| Rule ID | Error | | ||
|-------------------------------|----------------------------------------------------| | ||
| **max-line-length** | Line length must be no more than 120 but current length is 121. | | ||
| **payable-fallback** | When fallback is not payable you will not be able to receive ethers | | ||
| **no-empty-blocks** | Code contains empty block | | ||
| **no-unused-vars** | Variable "name" is unused | | ||
| **function-max-lines** | Function body contains "count" lines but allowed no more than "maxLines" lines | | ||
| **code-complexity** | Function has cyclomatic complexity "current" but allowed no more than "max" | | ||
| **max-states-count** | Contract has "curCount" states declarations but allowed no more than "max" | | ||
### Licence | ||
MIT |
@@ -102,5 +102,3 @@ | ||
disableRulesToEndOfFile(startLine, rules) { | ||
for (let i = startLine; i <= this.lastLine; i += 1) { | ||
this.disableRules(i, rules); | ||
} | ||
this._toEndOfFile(startLine, i => this.disableRules(i, rules)); | ||
} | ||
@@ -118,5 +116,3 @@ | ||
enableRulesToEndOfFile(startLine, rules) { | ||
for (let i = startLine; i <= this.lastLine; i += 1) { | ||
this.enableRules(i, rules); | ||
} | ||
this._toEndOfFile(startLine, i => this.enableRules(i, rules)); | ||
} | ||
@@ -128,4 +124,11 @@ | ||
_toEndOfFile(from, callback) { | ||
for (let i = from; i <= this.lastLine; i += 1) { | ||
callback && callback(i); | ||
} | ||
} | ||
} | ||
module.exports = CommentDirectiveParser; |
@@ -0,1 +1,2 @@ | ||
const { stopLine, lineOf } = require('./tokens'); | ||
@@ -9,10 +10,7 @@ | ||
countOfEmptyLinesBetweenTokens(start, end) { | ||
const startLine = (start.stop || start.symbol).line; | ||
const endLine = (end.start || end.symbol).line; | ||
return this.countOfEmptyLinesBetween(startLine, endLine); | ||
countOfEmptyLinesBetween(start, end) { | ||
return this.countOfEmptyLinesBetweenTokens(stopLine(start), lineOf(end)); | ||
} | ||
countOfEmptyLinesBetween(start, end) { | ||
countOfEmptyLinesBetweenTokens(start, end) { | ||
let count = 0; | ||
@@ -19,0 +17,0 @@ |
const _ = require('lodash'); | ||
const { hasNoSpaceAfter, hasNoSpacesBefore, hasSpaceAfter, hasSpaceBefore } = require('./tokens'); | ||
@@ -17,3 +18,3 @@ | ||
const validCase = this._validCase(); | ||
validCase && validCase.validate(once(callback)); | ||
validCase && validCase.validate(_.once(callback)); | ||
} | ||
@@ -64,3 +65,3 @@ | ||
const items = this.items; | ||
items.push(new NoSpaces(items[items.length - 1])); | ||
items.push(new NoSpaces(this.lastItem)); | ||
@@ -72,3 +73,3 @@ return this; | ||
const items = this.items; | ||
items.push(new Space(items[items.length - 1])); | ||
items.push(new Space(this.lastItem)); | ||
@@ -94,3 +95,3 @@ return this; | ||
if (this.syntaxMatch(ctx)) { | ||
this.validate(once(callback)); | ||
this.validate(_.once(callback)); | ||
} | ||
@@ -122,2 +123,8 @@ } | ||
} | ||
get lastItem() { | ||
const items = this.items; | ||
return items[items.length - 1]; | ||
} | ||
} | ||
@@ -197,6 +204,2 @@ | ||
class NoSpacesAround extends Term { | ||
constructor (...terms) { | ||
super(...terms); | ||
} | ||
listenError (callback) { | ||
@@ -212,6 +215,2 @@ const ctx = this.ctx; | ||
class SpaceAroundOrNot extends Term { | ||
constructor (...terms) { | ||
super(...terms); | ||
} | ||
listenError (callback) { | ||
@@ -230,6 +229,2 @@ const ctx = this.ctx; | ||
class SpaceAround extends Term { | ||
constructor (...terms) { | ||
super(...terms); | ||
} | ||
listenError (callback) { | ||
@@ -244,51 +239,25 @@ const ctx = this.ctx; | ||
function tokens(ctx) { | ||
let curCtx = ctx; | ||
while (curCtx && curCtx.parentCtx && !curCtx.parser) { | ||
curCtx = curCtx.parentCtx; | ||
} | ||
return curCtx.parser._input.tokens; | ||
function noSpacesAfter(ctx, thenRaise) { | ||
whenNot(hasNoSpaceAfter, ctx, thenRaise, 'Required no spaces after'); | ||
} | ||
function prevToken(ctx) { | ||
const token = ctx.start || ctx.symbol; | ||
const tokenList = tokens(ctx); | ||
const tokenIndex = _.sortedIndexBy(tokenList, token, token => token.start); | ||
let prevTokenIndex = tokenIndex - 1; | ||
while (prevTokenIndex >= 0 && tokenList[prevTokenIndex].channel !== 0) { | ||
prevTokenIndex -= 1; | ||
} | ||
return tokenList[prevTokenIndex]; | ||
function noSpacesBefore(ctx, thenRaise) { | ||
whenNot(hasNoSpacesBefore, ctx, thenRaise, 'Required no spaces before'); | ||
} | ||
function nextToken(ctx) { | ||
const token = ctx.stop || ctx.symbol; | ||
const tokenList = tokens(ctx); | ||
const tokenIndex = _.sortedIndexBy(tokenList, token, token => token.start); | ||
let nextTokenIndex = tokenIndex + 1; | ||
while (nextTokenIndex < tokenList.length && tokenList[nextTokenIndex].channel !== 0) { | ||
nextTokenIndex += 1; | ||
} | ||
return tokenList[nextTokenIndex]; | ||
function spaceBefore(ctx, thenRaise) { | ||
whenNot(hasSpaceBefore, ctx, thenRaise, 'Required space before'); | ||
} | ||
function hasNoSpaceAfter(ctx) { | ||
const token = ctx.stop || ctx.symbol; | ||
const _nextToken = nextToken(ctx); | ||
return _nextToken.start - token.stop === 1 || !onSameLine(token, _nextToken); | ||
function spaceAfter(ctx, thenRaise) { | ||
whenNot(hasSpaceAfter, ctx, thenRaise, 'Required space after'); | ||
} | ||
function noSpacesAfter(ctx, callback) { | ||
if (!hasNoSpaceAfter(ctx)) { | ||
callback && callback(ctx, `Required no spaces after ${ctx.getText()}`); | ||
function whenNot(conditionFn, ctx, callback, message) { | ||
if (!conditionFn(ctx)) { | ||
callback && callback(ctx, `${message} ${ctx.getText()}.`); | ||
} | ||
@@ -298,59 +267,2 @@ } | ||
function hasNoSpacesBefore(ctx) { | ||
const token = ctx.stop || ctx.symbol; | ||
const _prevToken = prevToken(ctx); | ||
return token.start - _prevToken.stop === 1 || !onSameLine(token, _prevToken); | ||
} | ||
function noSpacesBefore(ctx, callback) { | ||
if (!hasNoSpacesBefore(ctx)) { | ||
callback && callback(ctx, `Required no spaces after ${ctx.getText()}`); | ||
} | ||
} | ||
function hasSpaceBefore(ctx) { | ||
const token = ctx.stop || ctx.symbol; | ||
const _prevToken = prevToken(ctx); | ||
return token.start - _prevToken.stop === 2 || !onSameLine(token, _prevToken); | ||
} | ||
function spaceBefore(ctx, callback) { | ||
if (!hasSpaceBefore(ctx)) { | ||
callback && callback(ctx, `Required space after ${ctx.getText()}.`); | ||
} | ||
} | ||
function hasSpaceAfter(ctx) { | ||
const token = ctx.stop || ctx.symbol; | ||
const _nextToken = nextToken(ctx); | ||
return _nextToken.start - token.stop === 2 || !onSameLine(token, _nextToken); | ||
} | ||
function spaceAfter(ctx, callback) { | ||
if (!hasSpaceAfter(ctx)) { | ||
callback && callback(ctx, `Required space after ${ctx.getText()}.`); | ||
} | ||
} | ||
function once(callback) { | ||
let callsCount = 0; | ||
return (...args) => callsCount++ === 0 && callback(...args); | ||
} | ||
function onSameLine(token1, token2) { | ||
return token1.line === token2.line; | ||
} | ||
module.exports = { StatementsIndentValidator, Rule, Term }; |
@@ -47,2 +47,12 @@ | ||
findTypeInChildren(ctx, type) { | ||
if (ctx.children) { | ||
let items = ctx.children.filter(i => i.constructor.name === type); | ||
return items.length > 0 && items[0] || null; | ||
} else { | ||
return null; | ||
} | ||
} | ||
*findIdentifier(ctx) { | ||
@@ -62,30 +72,8 @@ const children = ctx.children; | ||
TreeTraversing.columnOf = function (ctx) { | ||
if (ctx && ctx.start) { | ||
return ctx.start.column; | ||
} else if (ctx && ctx.symbol) { | ||
return ctx.symbol.column; | ||
} else { | ||
return null; | ||
} | ||
}; | ||
TreeTraversing.lineOf = function (ctx) { | ||
if (ctx && ctx.start) { | ||
return ctx.start.line; | ||
} else if (ctx && ctx.symbol) { | ||
return ctx.symbol.line; | ||
} else { | ||
return null; | ||
} | ||
}; | ||
TreeTraversing.typeOf = function (ctx) { | ||
const className = ctx.constructor.name; | ||
const typeName = className.replace('Context', ''); | ||
TreeTraversing.stopLine = function (ctx) { | ||
if (ctx && ctx.stop) { | ||
return ctx.stop.line; | ||
} else if (ctx && ctx.symbol) { | ||
return ctx.symbol.line; | ||
} else { | ||
return null; | ||
} | ||
return typeName[0].toLowerCase() + typeName.substring(1); | ||
}; | ||
@@ -92,0 +80,0 @@ |
@@ -19,7 +19,4 @@ const CommentDirectiveParser = require('./comment-directive-parser'); | ||
const charAtLine = this.tokenStream.get(interval.start).column; | ||
const configSeverity = this.severityOf(ruleId); | ||
if (this.config[ruleId] !== false && this.commentDirectiveParser.isRuleEnabled(line, ruleId)) { | ||
this.addReport(line, charAtLine, configSeverity || defaultSeverity, message, ruleId); | ||
} | ||
this.addMessageExplicitLine(line, charAtLine, defaultSeverity, message, ruleId); | ||
} | ||
@@ -35,2 +32,14 @@ | ||
error(ctx, ruleId, message) { | ||
this.addMessage(ctx.getSourceInterval(), Reporter.SEVERITY.ERROR, message, ruleId); | ||
} | ||
warn(ctx, ruleId, message) { | ||
this.addMessage(ctx.getSourceInterval(), Reporter.SEVERITY.WARN, message, ruleId); | ||
} | ||
errorAt(line, column, ruleId, message) { | ||
this.addMessageExplicitLine(line, column, Reporter.SEVERITY.ERROR, message, ruleId); | ||
} | ||
severityOf(ruleId) { | ||
@@ -52,12 +61,13 @@ const ruleConfig = this.config[ruleId]; | ||
get errorCount() { | ||
return this | ||
.reports | ||
.filter(i => i.severity === Reporter.SEVERITY.ERROR) | ||
.length; | ||
return this._countReportsWith(Reporter.SEVERITY.ERROR); | ||
} | ||
get warningCount() { | ||
return this._countReportsWith(Reporter.SEVERITY.WARN); | ||
} | ||
_countReportsWith(severity) { | ||
return this | ||
.reports | ||
.filter(i => i.severity === Reporter.SEVERITY.WARN) | ||
.filter(i => i.severity === severity) | ||
.length; | ||
@@ -64,0 +74,0 @@ } |
@@ -1,62 +0,21 @@ | ||
const ExternalCallChecker = require('./external-call'); | ||
const CompilerVersionChecker = require('./fixed-compiler'); | ||
const ExplicitVisibilityChecker = require('./explicit-visibility'); | ||
const AvoidDeprecationsChecker = require('./avoid-deprecations'); | ||
const KeepFallbackSimpleChecker = require('./keep-fallback-simple'); | ||
const NoSimilarFuncEventNamesChecker = require('./no-similar-func-event-names'); | ||
const MultipleSendCallsInTxChecker = require('./multiple-send-calls-in-tx'); | ||
// const MarkUntrustedContractsChecker = require('./mark-unstrusted-contracts'); | ||
const FunctionNameStyleChecker = require('./func-name-style'); | ||
const FunctionParamNameStyleChecker = require('./func-params-style'); | ||
const VarNameStyleChecker = require('./var-name-style'); | ||
const EventNameStyleChecker = require('./event-name-style'); | ||
const ModifierNameStyleChecker = require('./modifier-name-style'); | ||
const ContractNameStyleChecker = require('./contract-library-style'); | ||
const ForbiddenNamesChecker = require('./forbidden-names'); | ||
const VisibilityModifierOrderChecker = require('./visibility-modifier-order'); | ||
const ImportsOnTopChecker = require('./imports-on-top'); | ||
const SeparateTopLevelByTwoLinesChecker = require('./separate-top-level-by-two-lines'); | ||
const FunctionOrderChecker = require('./function-order'); | ||
const security = require('./security/index'); | ||
const naming = require('./naming/index'); | ||
const order = require('./order/index'); | ||
const align = require('./align/index'); | ||
const bestPractises = require('./best-practises/index'); | ||
const QuotesChecker = require('./quotes'); | ||
const NoMixTabAndSpacesChecker = require('./no-mix-tabs-and-spaces'); | ||
const IndentChecker = require('./indent'); | ||
const BracketsAlign = require('./brackets-align'); | ||
const ArrayDeclarationChecker = require('./array-declaration'); | ||
const OneLineBetweenContractPartsChecker = require('./one-line-between-contract-parts'); | ||
const ExpressionAlignChecker = require('./expression-align'); | ||
const StatementsAlignChecker = require('./statements-align'); | ||
const MaxLineLengthChecker = require('./max-line-length'); | ||
const configObject = require('./../config'); | ||
module.exports = function checkers(reporter, config={}) { | ||
module.exports = function checkers(reporter, configVals={}) { | ||
const config = configObject.from(configVals); | ||
return [ | ||
new ExternalCallChecker(reporter), | ||
new CompilerVersionChecker(reporter), | ||
new ExplicitVisibilityChecker(reporter), | ||
new AvoidDeprecationsChecker(reporter), | ||
new KeepFallbackSimpleChecker(reporter), | ||
new NoSimilarFuncEventNamesChecker(reporter), | ||
new MultipleSendCallsInTxChecker(reporter), | ||
// new MarkUntrustedContractsChecker(reporter), | ||
new FunctionNameStyleChecker(reporter), | ||
new FunctionParamNameStyleChecker(reporter), | ||
new VarNameStyleChecker(reporter), | ||
new EventNameStyleChecker(reporter), | ||
new ModifierNameStyleChecker(reporter), | ||
new ContractNameStyleChecker(reporter), | ||
new ForbiddenNamesChecker(reporter), | ||
new VisibilityModifierOrderChecker(reporter), | ||
new ImportsOnTopChecker(reporter), | ||
new SeparateTopLevelByTwoLinesChecker(reporter), | ||
new FunctionOrderChecker(reporter), | ||
new QuotesChecker(reporter, config), | ||
new NoMixTabAndSpacesChecker(reporter, config), | ||
new IndentChecker(reporter, config), | ||
new BracketsAlign(reporter), | ||
new ArrayDeclarationChecker(reporter), | ||
new OneLineBetweenContractPartsChecker(reporter), | ||
new ExpressionAlignChecker(reporter), | ||
new StatementsAlignChecker(reporter), | ||
new MaxLineLengthChecker(reporter, config) | ||
...security(reporter, config), | ||
...order(reporter, config), | ||
...naming(reporter, config), | ||
...align(reporter, config), | ||
...bestPractises(reporter, config), | ||
new QuotesChecker(reporter, config) | ||
]; | ||
}; |
@@ -1,10 +0,8 @@ | ||
const Reporter = require('./../reporter'); | ||
const BaseChecker = require('./base-checker'); | ||
const SEVERITY = Reporter.SEVERITY; | ||
class QuotesChecker extends BaseChecker { | ||
class QuotesChecker { | ||
constructor(reporter, config) { | ||
this.reporter = reporter; | ||
super(reporter); | ||
@@ -50,11 +48,8 @@ const quoteType = config.rules && config.rules.quotes && config.rules.quotes[1]; | ||
if (ctx.getText().startsWith(this.incorrectQuote)) { | ||
this.makeReport(ctx); | ||
this._error(ctx); | ||
} | ||
} | ||
makeReport(ctx) { | ||
this.reporter.addMessage( | ||
ctx.getSourceInterval(), SEVERITY.ERROR, | ||
`Use ${this.quoteType} quotes for string literals`, 'quotes' | ||
); | ||
_error(ctx) { | ||
this.error(ctx, 'quotes', `Use ${this.quoteType} quotes for string literals`); | ||
} | ||
@@ -61,0 +56,0 @@ } |
@@ -6,3 +6,3 @@ const SolidityListener = require('./grammar/SolidityListener').SolidityListener; | ||
constructor(checkers = []) { | ||
constructor(checkers) { | ||
super(); | ||
@@ -42,3 +42,3 @@ this.listenersMap = { }; | ||
notifyListenersOn(methodName) { | ||
return (ctx) => this.listenersFor(methodName).forEach(fn => fn(ctx)); | ||
return (ctx) => this.listenersFor(methodName).forEach(fn => quite(fn)(ctx)); | ||
} | ||
@@ -49,2 +49,13 @@ | ||
function quite(fn) { | ||
return (...args) => { | ||
try { | ||
fn && fn.call(fn, ...args); | ||
} catch (err) { | ||
// console.log(err); | ||
} | ||
}; | ||
} | ||
module.exports = SecurityErrorListener; |
{ | ||
"name": "solhint", | ||
"version": "1.0.15", | ||
"version": "1.1.0", | ||
"description": "Solidity Code Linter", | ||
@@ -20,3 +20,3 @@ "main": "solhint.js", | ||
"exec-tests": "nyc -x \"**/grammar/**\" mocha && nyc report --reporter=text-lcov | coveralls", | ||
"test": "eslint *.js lib/*.js lib/rules/*.js test/*.js && npm run exec-tests" | ||
"test": "eslint *.js lib/*.js lib/rules/*.js lib/rules/**/*.js test/*.js && npm run exec-tests" | ||
}, | ||
@@ -23,0 +23,0 @@ "bin": { |
@@ -124,2 +124,3 @@ ## Solhint Project | ||
| **no-simple-event-func-name** | Event and function names must be different | | ||
| **avoid-tx-origin** | Avoid to use tx.origin | | ||
@@ -151,4 +152,21 @@ ### Style Guide Codes: | ||
| **max-line-length** | Line length must be no more than 120 but current length is 121. | | ||
| **payable-fallback** | When fallback is not payable you will not be able to receive ethers | | ||
| **no-empty-blocks** | Code contains empty block | | ||
| **no-unused-vars** | Variable "name" is unused | | ||
| **function-max-lines** | Function body contains "count" lines but allowed no more than "maxLines" lines | | ||
| **space-after-comma** | Comma must be separated from next element by space | | ||
| **no-spaces-before-semicolon**| Semicolon must not have spaces before | | ||
### Best Practise Codes: | ||
| Rule ID | Error | | ||
|-------------------------------|----------------------------------------------------| | ||
| **max-line-length** | Line length must be no more than 120 but current length is 121. | | ||
| **payable-fallback** | When fallback is not payable you will not be able to receive ethers | | ||
| **no-empty-blocks** | Code contains empty block | | ||
| **no-unused-vars** | Variable "name" is unused | | ||
| **function-max-lines** | Function body contains "count" lines but allowed no more than "maxLines" lines | | ||
| **code-complexity** | Function has cyclomatic complexity "current" but allowed no more than "max" | | ||
| **max-states-count** | Contract has "curCount" states declarations but allowed no more than "max" | | ||
### Documentation | ||
@@ -155,0 +173,0 @@ |
@@ -80,3 +80,3 @@ #!/usr/bin/env node | ||
const readConfig = _.curry(function () { | ||
const readConfig = _.memoize(function () { | ||
try { | ||
@@ -83,0 +83,0 @@ const configStr = fs.readFileSync('.solhint.json').toString(); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3995384
144
19312
176