-
Notifications
You must be signed in to change notification settings - Fork 153
/
explicit-types.js
125 lines (106 loc) · 3.56 KB
/
explicit-types.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
const BaseChecker = require('../base-checker')
const { severityDescription, formatEnum } = require('../../doc/utils')
const EXPLICIT_TYPES = ['uint256', 'int256', 'ufixed128x18', 'fixed128x18']
const IMPLICIT_TYPES = ['uint', 'int', 'ufixed', 'fixed']
const ALL_TYPES = EXPLICIT_TYPES.concat(IMPLICIT_TYPES)
const VALID_CONFIGURATION_OPTIONS = ['explicit', 'implicit']
const DEFAULT_OPTION = 'explicit'
const DEFAULT_SEVERITY = 'warn'
const ruleId = 'explicit-types'
const meta = {
type: 'best-practises',
docs: {
description: 'Forbid or enforce explicit types (like uint256) that have an alias (like uint).',
category: 'Best Practise Rules',
options: [
{
description: severityDescription,
default: DEFAULT_SEVERITY,
},
{
description: `Options need to be one of ${formatEnum(VALID_CONFIGURATION_OPTIONS)}`,
default: DEFAULT_OPTION,
},
],
examples: {
good: [
{
description: 'If explicit is selected',
code: 'uint256 public variableName',
},
{
description: 'If implicit is selected',
code: 'uint public variableName',
},
],
bad: [
{
description: 'If explicit is selected',
code: 'uint public variableName',
},
{
description: 'If implicit is selected',
code: 'uint256 public variableName',
},
],
},
},
isDefault: false,
recommended: true,
defaultSetup: [DEFAULT_SEVERITY, DEFAULT_OPTION],
schema: {
type: 'string',
enum: VALID_CONFIGURATION_OPTIONS,
},
}
class ExplicitTypesChecker extends BaseChecker {
constructor(reporter, config) {
super(reporter, ruleId, meta)
this.configOption = (config && config.getString(ruleId, DEFAULT_OPTION)) || DEFAULT_OPTION
this.isExplicit = this.configOption === 'explicit'
}
VariableDeclaration(node) {
if (!VALID_CONFIGURATION_OPTIONS.includes(this.configOption)) {
this.error(node, 'Error: Config error on [explicit-types]. See explicit-types.md.')
return
}
const typeToFind = 'ElementaryTypeName'
const onlyTypes = this.findNamesOfElementaryTypeName(node, typeToFind)
// if no variables are defined, return
if (onlyTypes && onlyTypes.length === 0) return
// this tells if the variable needs to be checked
const varsToBeChecked = onlyTypes.filter((type) => ALL_TYPES.includes(type))
// if defined variables are not to be checked (example address type), return
if (varsToBeChecked && varsToBeChecked.length === 0) return
// if explicit, it will search for implicit and viceversa
if (this.isExplicit) {
this.validateVariables(IMPLICIT_TYPES, node, varsToBeChecked)
} else {
this.validateVariables(EXPLICIT_TYPES, node, varsToBeChecked)
}
}
validateVariables(configType, node, varsToBeChecked) {
const errorVars = varsToBeChecked.filter((type) => configType.includes(type))
if (errorVars && errorVars.length > 0) {
for (const errorVar of errorVars) {
this.error(node, `Rule is set with ${this.configOption} type [var/s: ${errorVar}]`)
}
}
}
findNamesOfElementaryTypeName(jsonObject, typeToFind) {
const names = []
const searchInObject = (obj) => {
if (obj.type === typeToFind && obj.name) {
names.push(obj.name)
}
for (const key in obj) {
if (typeof obj[key] === 'object' && obj[key] !== null) {
searchInObject(obj[key])
}
}
}
searchInObject(jsonObject)
return names
}
}
module.exports = ExplicitTypesChecker