-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathescomplex.node.txt
More file actions
262 lines (246 loc) · 18.5 KB
/
escomplex.node.txt
File metadata and controls
262 lines (246 loc) · 18.5 KB
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
┏━━━━━━━━━━━━━━━┓
┃ ESCOMPLEX ┃
┗━━━━━━━━━━━━━━━┛
VERSION ==> #2.0.0-alpha (the one from 20/07/2017)
#Must use GitHub URL to get real last version
#JavaScript complexity static analysis
#Only ESTree es5 spec, not es2015, es2016, es2017, extensions nor experimental.
#Also some deprecated ESTree are still there.
ESCOMPLEX.analyse('JS'|OBJ_ARR #Returns an OBJ
[, OPTS][, POPTS|FUNC]) #OBJ_ARR: code 'JS', path 'PATH'
#If 'JS' is passed, only returns one reports OBJ, and no reports.path
#Uses Espree for AST parsing:
# - using espree.parse(..., OBJ), where OBJ:
# - is { ecmaVersion: 8, loc: true }
# - can be partially assigned with POPTS
# - can use FUNC to define custom parser FUNC('JS', POPTS):
# - esprima and acorn are supported
#OPTS:
# - skipCalculation true: only returns reports OBJ
# - noCoreSize true: do not calculate visibilityMatrix|changeCost|coreSize
# - ignoreErrors true: ignore parsing errors
┌──────────────────┐
│ RETURN VALUE │
└──────────────────┘
RETURN VALUE ==> # - reports:
# - path 'PATH'
# - functions (each NODE.newScope true creates new one):
# - name 'FUNC'
# - params NUM
# - line NUM: line position number
# - sloc:
# - logical NUM: number of "logical lines"
# - physical NUM: number of source lines
# - cyclomatic NUM:
# - number of possible branches
# - starts at 1
# - cyclomaticDensity NUM:
# - average possible branches per source line
# - (cyclomatic / sloc.physical) * 100
# - halstead:
# - operators:
# - identifiers 'TOKEN'_ARR: each unique "operator"
# - distinct NUM: number of unique "operator"
# - total NUM: number of "operator"
# - operands:
# - like halstead.operators, but for "operands"
# - length:
# - number of "operators|operands"
# - operators.total + operands.total
# - vocabulary:
# - number of unique "operators|operands"
# - operators.distinct + operands.distinct
# - volume:
# - size of the function:
# - increased by number of "operators|operands"
# - decreased by repetitiveness of "operators|operands"
# - is linearithmic, i.e. increases more and more
# - length * log(vocabulary) * 1/log(2)
# - bugs:
# - estimation of number bugs, according to how often bugs appear per volume of code
# - volume / 3000
# - difficulty:
# - how much code can be refactored:
# - increased by non-repetitiveness of "operators" and repetitiveness of "operands"
# - i.e. should create many operators that take few operands
# - also increased by number of unique "operators", i.e. logic size
# - (operators.distinct / 2) * (operands.total / operands.distinct)
# - effort:
# - volume * difficulty
# - time:
# - estimation of how many seconds to write that function
# - effort / 18
# - aggregate:
# - sum of all the report.functions.* for: params, sloc.logical, cyclomatic,
# cyclomaticDensity, halstead.*
# - same OBJ for those
# - params|loc|cyclomatic|effort NUM:
# - average of all the report.functions.* for: params, sloc.logical, cyclomatic,
# halstead.effort
# - if no report.functions.*, uses report.aggregate instead
# - maintainability NUM:
# - "maintainability index", combination of average halstead.effort, cyclomatic and sloc.logical
# - cyclomatic has almost no impact, and sloc.logical has twice more impact than halstead.effort
# - is between 0 and 171:
# - uses a logarithmic scale, i.e. could theoritically go below 0, but it's hard to go below 30
# - can be normalized to 0 to 100 using OPTS.newmi true (def: false)
# - 171 - (3.42 * Math.log(reports.effort)) - (0.23 * Math.log(reports.cyclomatic)) - (16.2 * Math.log(reports.loc))
# - dependencies OBJ_ARR:
# - line NUM (line number)
# - type 'CommonJS' or 'AMD'
# - path 'MDL' or (if not literal value) '* dynamic dependency|ies *'
# - will use real 'MDL' if 'AMD' aliases were configured using
# require.config(CONFVAR paths)
# - params|loc|cyclomatic|effort|maintainability NUM: average of all the report.*
# - adjacencyMatrix ARR_ARR_NUM:
# - table of 1|0 of whether each file requires each file
# - each dimension is sorted by path
# - firstOrderDensity NUM:
# - how much files require each other
# - percentage of 1 inside adjacencyMatrix
# - visibilityMatrix ARR_ARR_NUM:
# - like ajacencyMatrix, except include deep dependencies
# - changeCost NUM:
# - modularity of the code:
# - more precisely, average number of deep dependencies per file
# - favor:
# - many modules, i.e. a -> b -> c is worst than a -> b
# -> c
# - shallow modules, i.e. a -> b -> c is worst than a -> c
# -> d -> d
# - this means files used only as abstraction layers (e.g. forwarding index.js)
# will be penalties, even though they are only forwarding dependencies
# - percentage of 1 inside visibilitryMatrix
# - coreSize NUM:
# - percentage of files that both:
# - have many dependencies
# - are used as dependency by many files
# - "many" means more than the median number per file
# - i.e. files in the middle of the dependencies chain, neither leaves nor top
# - high number means low modularity
SOURCE OF RETURN VALUE ==> #Source of each value:
# - reports (for each file):
# - path: user-supplied
# - functions: each NODE.newScope true creates new one
# - name: either NODE.id, NODE.assignedName or '<anonymous>'
# - params: NODE.params.length
# - line: NODE.loc
# - sloc:
# - logical: NODE.lloc
# - physical: NODE.loc
# - cyclomatic: NODE.cyclomatic
# - cyclomaticDensity: sloc.physical, cyclomatic
# - halstead:
# - operators: NODE.operators
# - operands: NODE.operands
# - length|vocabulary|volume|bugs|difficulty|effort|time: halstead.operarors|operands
# - aggregate: reports.functions.*
# - params|loc|cyclomatic|effort: reports.functions.*
# - maintainability: reports.loc|cyclomatic|effort
# - dependencies: NODE.dependencies
# - params|loc|cyclomatic|effort|maintainability: report.*
# - adjacencyMatrix|firstOrderDensity|visibiliyMatrix|changeCost|coreSize: reports.dependencies
ESTREE NODE SOURCE ==> #All those stats comes from each ESTree node type defining the following properties:
# - lloc NUM:
# - numbers of "logical lines":
# - a full statement, or could be reduced to one:
# - break|continue|return|throw
# - declaration
# - EXPR
# - FUNC()
# - OBJ.VAR, VAR: VAL (in OBJ)
# - a structure: do for forin if else switch case while with try catch
# - usually 1 or (for compound like if|else) sometimes 2
# - not for:
# - parts of an EXPR: usual operators, ?:, {}, []
# - debugger
# - cyclomatic NUM:
# - number of possible branches
# - is 1 for: catch, dowhile|while, forin|for, if|?:|switch|case, &&, ||
# - can ignore some with OPTS.trycatch|forin|switchcase|logicalor false
# (def: false|false|true|true)
# - operators 'TOKEN'[_ARR] or { filter(NODE)->BOOL, identifier 'TOKEN'[(NODE)] }[_ARR]:
# - "operator", i.e. functions (in an abstract senses)
# - including:
# - usual FUNC()
# - usual operators: = += + === ^ in instanceof && ! typeof delete ++ ...
# - also operators: ?: OBJ.VAR : (of VAR: VAL) const|let|var
# - keywords: break continue return throw
# - literal constructors: {}, [], FUNC declaration
# - structures: catch dowhile forin for if else switch case while with
# - not counted:
# - debugger
# - syntactic part of an operator: { } try ; , LABEL
# - bigger|complex nodes: ExpressionStatement
# - stored as the main representation, e.g. '=' for a declaration
# - "filter" is a test function
# - operands FUNC(NODE)->'VAL' or ARR of them
# - "operands", i.e. variables and literal values, i.e. operator's input
# - stored as the main representation, i.e.:
# - VAR: 'VAR'
# - FUNC: 'FUNC' name
# - ARR_LIT|OBJ_LIT: '<anonymous>'
# - STR_LIT: "STR"
# - BOOL|NUM|null|REGEXP_LIT: as is
# - dependencies(NODE, BOOL)->OBJ_ARR:
# - like of path required by require[.config](...)
# - only present on FUNC(...) that are require[.config](...)
# - since AMD aliases are used, using BOOL true resets them
# - OBJ_ARR is same as reports.dependencies
# - children STR[_ARR]
# - used by recursive walker
# - newScope BOOL:
# - true for FUNC declarations
# - used during recursion to indicate new function scope
# - assignedName(NODE)->'VAR':
# - name of the NODE, when NODE.id is not defined
┌──────────────┐
│ REPORTER │
└──────────────┘
COMPLEXITY-REPORT ==> #CLI on top of escomplex
#Version 2.0.0-alpha (the one from 12/03/2017)
CONF ==> #Can be:
# - cr --OPT OPT_VAL
# - .complexrc JSON_FILE
# - cr --config JSON_FILE
cr FILE|DIR #Runs ESCOMPLEX.analyse() on all files.
#Exit code will be:
# - 1 on file error: wrong config file, cannot parse source files, cannot write report file
# - 2 if complexity is too high in one of the files, according to --max*
#If first line is #!/bin/node, it is commented out
--allfiles #Include dotfiles (def: off)
--filepattern "REGEXP" #Def: "\\.js$"
#In all cases, only *.js files are considered
--dirpattern "REGEXP" #
--excludepattern "REGEXP" #For directories
--maxfiles NUM #Def: 1024
#Max number of files read at once
--format STR #Prints to console the result of ESCOMPLEX.analyse()
#Among:
# - "plain" (def): plain text
# - "modules": newline-separated list of "FILE"
# - "minimal": newline-separated list of "FILE: MAINTAINABILITY"
# followed by each "FUNC (LINE_NUM) CYCLOMATIC"
# - "markdown"
# - "json"
# - "xml"
# - "checkstyle"
#Can be 'MDL' with FUNC(OBJ)->STR, with OBJ being the result of ESCOMPLEX.analyse()
--output FILE #Prints to file instead
--silent #Do not print to console nor file
--trycatch
--forin
--switchcase
--logicalor
--newmi
--nocoresize
--ignoreerrors #ESComplex OPTS
--maxcyc NUM
--maxcycden NUM
--maxhv NUM
--maxhd NUM
--maxhe NUM
--minmi NUM #Maximum complexity for:
--maxfod NUM # - any function's cyclomatic, cyclomaticDensity, halstead.volume|difficulty|effort
--maxcost NUM # - any file's maintainability
--maxsize NUM # - firstOrderDensity, changeCost, coreSize