@jdeighan/coffee-utils 7.0.49 → 7.0.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/arrow.coffee +40 -4
- package/src/arrow.js +46 -5
- package/src/call_stack.coffee +93 -46
- package/src/call_stack.js +94 -47
- package/src/coffee_utils.coffee +12 -0
- package/src/coffee_utils.js +11 -0
- package/src/debug_utils.coffee +211 -145
- package/src/debug_utils.js +245 -138
- package/src/log_utils.coffee +49 -26
- package/src/log_utils.js +48 -27
package/src/debug_utils.coffee
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# debug_utils.coffee
|
2
2
|
|
3
3
|
import {
|
4
|
-
assert, undef, error, croak, warn,
|
4
|
+
assert, undef, error, croak, warn, defined,
|
5
|
+
isString, isFunction, isBoolean, sep_dash,
|
5
6
|
OL, escapeStr, isNumber, isArray, words, pass,
|
6
7
|
} from '@jdeighan/coffee-utils'
|
7
8
|
import {blockToArray} from '@jdeighan/coffee-utils/block'
|
@@ -9,17 +10,134 @@ import {untabify} from '@jdeighan/coffee-utils/indent'
|
|
9
10
|
import {slurp} from '@jdeighan/coffee-utils/fs'
|
10
11
|
import {CallStack} from '@jdeighan/coffee-utils/stack'
|
11
12
|
import {
|
12
|
-
|
13
|
+
getPrefix, addArrow, removeLastVbar,
|
14
|
+
} from '@jdeighan/coffee-utils/arrow'
|
15
|
+
import {
|
16
|
+
log, logItem, LOG, shortEnough,
|
13
17
|
} from '@jdeighan/coffee-utils/log'
|
14
18
|
|
15
|
-
|
16
|
-
export debugging = false
|
17
|
-
shouldLogFunc = (func) -> debugging
|
18
|
-
shouldLogString = (str) -> debugging
|
19
|
-
|
20
|
-
stack = new CallStack()
|
19
|
+
callStack = new CallStack()
|
21
20
|
doDebugDebug = false
|
22
21
|
|
22
|
+
export shouldLog = undef # set in resetDebugging() and setDebugging()
|
23
|
+
export lFuncList = []
|
24
|
+
|
25
|
+
# ---------------------------------------------------------------------------
|
26
|
+
|
27
|
+
export debug = (label, lObjects...) ->
|
28
|
+
|
29
|
+
assert isString(label), "1st arg #{OL(label)} should be a string"
|
30
|
+
|
31
|
+
# --- We want to allow objects to be undef. Therefore, we need to
|
32
|
+
# distinguish between 1 arg sent vs. 2 or more args sent
|
33
|
+
nObjects = lObjects.length
|
34
|
+
|
35
|
+
# --- funcName is only set for types 'enter' and 'return'
|
36
|
+
[type, funcName] = getType(label, nObjects)
|
37
|
+
if doDebugDebug
|
38
|
+
LOG "debug(): type = #{OL(type)}"
|
39
|
+
LOG "debug(): funcName = #{OL(funcName)}"
|
40
|
+
|
41
|
+
switch type
|
42
|
+
when 'enter'
|
43
|
+
callStack.enter funcName
|
44
|
+
label = shouldLog(label, type, funcName, callStack)
|
45
|
+
when 'return'
|
46
|
+
label = shouldLog(label, type, funcName, callStack)
|
47
|
+
when 'string'
|
48
|
+
label = shouldLog(label, type, undef, callStack)
|
49
|
+
assert (nObjects == 0),
|
50
|
+
"multiple objects only not allowed for #{OL(type)}"
|
51
|
+
when 'objects'
|
52
|
+
label = shouldLog(label, type, undef, callStack)
|
53
|
+
assert (nObjects > 0),
|
54
|
+
"multiple objects only not allowed for #{OL(type)}"
|
55
|
+
doLog = defined(label)
|
56
|
+
|
57
|
+
if doDebugDebug
|
58
|
+
if nObjects == 0
|
59
|
+
LOG "debug(#{OL(label)}) - 1 arg"
|
60
|
+
else
|
61
|
+
LOG "debug(#{OL(label)}), #{nObjects} args"
|
62
|
+
LOG "doLog = #{OL(doLog)}"
|
63
|
+
|
64
|
+
if doLog
|
65
|
+
level = callStack.getLevel()
|
66
|
+
prefix = getPrefix(level)
|
67
|
+
|
68
|
+
if doDebugDebug
|
69
|
+
LOG "callStack", callStack
|
70
|
+
LOG "level = #{OL(level)}"
|
71
|
+
LOG "prefix = #{OL(prefix)}"
|
72
|
+
|
73
|
+
switch type
|
74
|
+
when 'enter'
|
75
|
+
log label, {prefix}
|
76
|
+
for obj,i in lObjects
|
77
|
+
if (i > 0)
|
78
|
+
log sep_dash, {prefix: removeLastVbar(prefix)}
|
79
|
+
logItem undef, obj, {prefix: removeLastVbar(prefix)}
|
80
|
+
when 'return'
|
81
|
+
log label, {prefix: addArrow(prefix)}
|
82
|
+
for obj,i in lObjects
|
83
|
+
if (i > 0)
|
84
|
+
log sep_dash, {prefix: removeLastVbar(prefix)}
|
85
|
+
logItem undef, obj, {prefix: removeLastVbar(prefix)}
|
86
|
+
when 'string'
|
87
|
+
log label, {prefix}
|
88
|
+
when 'objects'
|
89
|
+
if (nObjects==1) && shortEnough(label, lObjects[0])
|
90
|
+
logItem label, lObjects[0], {prefix}
|
91
|
+
else
|
92
|
+
if (label.indexOf(':') != label.length - 1)
|
93
|
+
label += ':'
|
94
|
+
log label, {prefix}
|
95
|
+
for obj in lObjects
|
96
|
+
logItem undef, obj, {prefix}
|
97
|
+
|
98
|
+
if (type == 'enter') && doLog
|
99
|
+
callStack.logCurFunc()
|
100
|
+
else if (type == 'return')
|
101
|
+
callStack.returnFrom funcName
|
102
|
+
|
103
|
+
return true # allow use in boolean expressions
|
104
|
+
|
105
|
+
# ---------------------------------------------------------------------------
|
106
|
+
|
107
|
+
export stdShouldLog = (label, type, funcName, stack) ->
|
108
|
+
# --- if type is 'enter', then funcName won't be on the stack yet
|
109
|
+
# returns the (possibly modified) label to log
|
110
|
+
|
111
|
+
# --- If we're logging now,
|
112
|
+
# but we won't be logging when funcName is activated
|
113
|
+
# then change 'enter' to 'call'
|
114
|
+
|
115
|
+
assert isString(label), "label #{OL(label)} not a string"
|
116
|
+
assert isString(type), "type #{OL(type)} not a string"
|
117
|
+
if (type == 'enter') || (type == 'return')
|
118
|
+
assert isString(funcName), "func name #{OL(funcName)} not a string"
|
119
|
+
else
|
120
|
+
assert funcName == undef, "func name #{OL(funcName)} not undef"
|
121
|
+
assert stack instanceof CallStack, "not a call stack object"
|
122
|
+
if doDebugDebug
|
123
|
+
LOG "stdShouldLog(#{OL(label)}, #{OL(type)}, #{OL(funcName)}, stack)"
|
124
|
+
LOG "stack", stack
|
125
|
+
LOG "lFuncList", lFuncList
|
126
|
+
switch type
|
127
|
+
when 'enter'
|
128
|
+
if funcMatch(stack, lFuncList)
|
129
|
+
return label
|
130
|
+
|
131
|
+
# --- As a special case, if we enter a function where we will not
|
132
|
+
# be logging, but we were logging in the calling function,
|
133
|
+
# we'll log out the call itself
|
134
|
+
else if stack.isLoggingPrev()
|
135
|
+
return label.replace('enter', 'call')
|
136
|
+
else
|
137
|
+
if funcMatch(stack, lFuncList)
|
138
|
+
return label
|
139
|
+
return undef
|
140
|
+
|
23
141
|
# ---------------------------------------------------------------------------
|
24
142
|
|
25
143
|
export debugDebug = (flag=true) ->
|
@@ -33,176 +151,124 @@ export debugDebug = (flag=true) ->
|
|
33
151
|
|
34
152
|
resetDebugging = () ->
|
35
153
|
|
36
|
-
debugging = false
|
37
154
|
if doDebugDebug
|
38
|
-
LOG "resetDebugging()
|
39
|
-
|
40
|
-
|
41
|
-
shouldLogString = (str) -> debugging
|
155
|
+
LOG "resetDebugging()"
|
156
|
+
callStack.reset()
|
157
|
+
shouldLog = (label, type, funcName, stack) -> undef
|
42
158
|
return
|
43
159
|
|
44
160
|
# ---------------------------------------------------------------------------
|
45
161
|
|
46
|
-
export setDebugging = (
|
162
|
+
export setDebugging = (option) ->
|
47
163
|
|
48
164
|
resetDebugging()
|
49
|
-
if isBoolean(
|
50
|
-
|
165
|
+
if isBoolean(option)
|
166
|
+
if option
|
167
|
+
shouldLog = (label, type, funcName, stack) -> label
|
168
|
+
else
|
169
|
+
shouldLog = (label, type, funcName, stack) -> undef
|
51
170
|
if doDebugDebug
|
52
|
-
LOG "setDebugging
|
53
|
-
else if isString(
|
54
|
-
|
55
|
-
|
56
|
-
assert isArray(lFuncNames), "words('#{funcDoDebug}') returned non-array"
|
57
|
-
shouldLogFunc = (funcName) ->
|
58
|
-
funcMatch(funcName, lFuncNames)
|
171
|
+
LOG "setDebugging = #{option}"
|
172
|
+
else if isString(option)
|
173
|
+
lFuncList = getFuncList(option)
|
174
|
+
shouldLog = stdShouldLog
|
59
175
|
if doDebugDebug
|
60
|
-
LOG "setDebugging FUNCS: #{
|
61
|
-
|
62
|
-
|
176
|
+
LOG "setDebugging FUNCS: #{option}"
|
177
|
+
LOG 'lFuncList', lFuncList
|
178
|
+
else if isFunction(option)
|
179
|
+
shouldLog = option
|
63
180
|
if doDebugDebug
|
64
181
|
LOG "setDebugging to custom func"
|
65
182
|
else
|
66
|
-
croak "
|
67
|
-
|
68
|
-
if funcDoLog
|
69
|
-
assert isFunction(funcDoLog), "setDebugging: arg 2 not a function"
|
70
|
-
shouldLogString = funcDoLog
|
183
|
+
croak "bad parameter #{OL(option)}"
|
71
184
|
return
|
72
185
|
|
73
186
|
# ---------------------------------------------------------------------------
|
74
187
|
# --- export only to allow unit tests
|
75
188
|
|
76
|
-
export
|
189
|
+
export getFuncList = (str) ->
|
190
|
+
|
191
|
+
lFuncList = []
|
192
|
+
for word in words(str)
|
193
|
+
if lMatches = word.match(///^
|
194
|
+
([A-Za-z_][A-Za-z0-9_]*)
|
195
|
+
(?:
|
196
|
+
\.
|
197
|
+
([A-Za-z_][A-Za-z0-9_]*)
|
198
|
+
)?
|
199
|
+
(\+)?
|
200
|
+
$///)
|
201
|
+
[_, ident1, ident2, plus] = lMatches
|
202
|
+
if ident2
|
203
|
+
lFuncList.push {
|
204
|
+
name: ident2
|
205
|
+
object: ident1
|
206
|
+
plus: (plus == '+')
|
207
|
+
}
|
208
|
+
else
|
209
|
+
lFuncList.push {
|
210
|
+
name: ident1
|
211
|
+
plus: (plus == '+')
|
212
|
+
}
|
213
|
+
else
|
214
|
+
croak "Bad word in func list: #{OL(word)}"
|
215
|
+
return lFuncList
|
77
216
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
217
|
+
# ---------------------------------------------------------------------------
|
218
|
+
# --- export only to allow unit tests
|
219
|
+
|
220
|
+
export funcMatch = (stack, lFuncList) ->
|
221
|
+
|
222
|
+
assert isArray(lFuncList), "not an array #{OL(lFuncList)}"
|
223
|
+
|
224
|
+
curFunc = stack.curFunc()
|
225
|
+
if doDebugDebug
|
226
|
+
LOG "funcMatch(): curFunc = #{OL(curFunc)}"
|
227
|
+
stack.dump(' ')
|
228
|
+
LOG 'lFuncList', lFuncList
|
229
|
+
for h in lFuncList
|
230
|
+
{name, object, plus} = h
|
231
|
+
if (name == curFunc)
|
232
|
+
if doDebugDebug
|
233
|
+
LOG " curFunc in lFuncList - match successful"
|
234
|
+
return true
|
235
|
+
if plus && stack.isActive(name)
|
236
|
+
if doDebugDebug
|
237
|
+
LOG " func #{OL(name)} is active - match successful"
|
238
|
+
return true
|
239
|
+
if doDebugDebug
|
240
|
+
LOG " - no match"
|
241
|
+
return false
|
88
242
|
|
89
243
|
# ---------------------------------------------------------------------------
|
90
|
-
#
|
91
|
-
# 2. adjust debugging flag
|
92
|
-
# 3. return [mainPrefix, auxPrefix, hEnv] - hEnv can be undef
|
93
|
-
# 4. disable logging by setting mainPrefix to undef
|
244
|
+
# --- type is one of: 'enter', 'return', 'string', 'object'
|
94
245
|
|
95
|
-
|
246
|
+
export getType = (str, nObjects) ->
|
96
247
|
|
97
|
-
if
|
248
|
+
if lMatches = str.match(///^
|
98
249
|
\s*
|
99
250
|
enter
|
100
251
|
\s+
|
101
252
|
([A-Za-z_][A-Za-z0-9_\.]*)
|
102
|
-
///)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
}
|
109
|
-
debugging = shouldLogFunc(curFunc)
|
110
|
-
if doDebugDebug
|
111
|
-
trans = "#{hEnv.debugging} => #{debugging}"
|
112
|
-
LOG " ENTER #{curFunc}, debugging: #{trans}"
|
113
|
-
[mainPre, auxPre, _] = stack.call(curFunc, hEnv, debugging)
|
114
|
-
return [
|
115
|
-
mainPre
|
116
|
-
auxPre
|
117
|
-
undef
|
118
|
-
if shouldLogFunc(curFunc) then 'enter' else undef
|
119
|
-
]
|
120
|
-
else if (lMatches = str.match(///^
|
253
|
+
///)
|
254
|
+
|
255
|
+
# --- We are entering function curFunc
|
256
|
+
return ['enter', lMatches[1]]
|
257
|
+
|
258
|
+
else if lMatches = str.match(///^
|
121
259
|
\s*
|
122
260
|
return
|
123
261
|
.+
|
124
262
|
from
|
125
263
|
\s+
|
126
264
|
([A-Za-z_][A-Za-z0-9_\.]*)
|
127
|
-
///)
|
128
|
-
|
129
|
-
[mainPre, auxPre, hEnv] = stack.returnFrom(curFunc)
|
130
|
-
if doDebugDebug
|
131
|
-
LOG " RETURN FROM #{curFunc}"
|
132
|
-
return [
|
133
|
-
mainPre
|
134
|
-
auxPre
|
135
|
-
hEnv
|
136
|
-
if shouldLogFunc(curFunc) then 'return' else undef
|
137
|
-
]
|
138
|
-
else
|
139
|
-
[mainPre, auxPre, _] = stack.logStr()
|
140
|
-
return [
|
141
|
-
mainPre
|
142
|
-
auxPre
|
143
|
-
undef
|
144
|
-
if shouldLogString(str) then 'string' else undef
|
145
|
-
]
|
146
|
-
|
147
|
-
# ---------------------------------------------------------------------------
|
148
|
-
|
149
|
-
export debug = (lArgs...) ->
|
265
|
+
///)
|
266
|
+
return ['return', lMatches[1]]
|
150
267
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
[label, item] = lArgs
|
156
|
-
assert isString(label),
|
157
|
-
"debug(): 1st arg #{OL(label)} should be a string"
|
158
|
-
|
159
|
-
if doDebugDebug
|
160
|
-
if nArgs==1
|
161
|
-
LOG "debug('#{escapeStr(label)}') - 1 arg"
|
162
|
-
else
|
163
|
-
LOG "debug('#{escapeStr(label)}', #{typeof item}) - 2 args"
|
164
|
-
LOG "debugging flag = #{OL(debugging)}"
|
165
|
-
|
166
|
-
# --- We always need to manipulate the stack when we encounter
|
167
|
-
# either "enter X" or "return from X", so we can't short-circuit
|
168
|
-
# when debugging is off
|
169
|
-
|
170
|
-
lResult = adjustStack(label)
|
171
|
-
if doDebugDebug
|
172
|
-
LOG 'lResult', lResult
|
173
|
-
[mainPre, auxPre, hEnv, type] = lResult
|
174
|
-
if doDebugDebug && (type == undef)
|
175
|
-
LOG "type is undef - NOT LOGGING"
|
176
|
-
|
177
|
-
hOptions = {
|
178
|
-
prefix: mainPre
|
179
|
-
itemPrefix: auxPre
|
180
|
-
}
|
181
|
-
|
182
|
-
switch type
|
183
|
-
when 'enter'
|
184
|
-
log label, hOptions
|
185
|
-
if (nArgs==2)
|
186
|
-
# --- don't repeat the label
|
187
|
-
logItem undef, item, hOptions
|
188
|
-
when 'return'
|
189
|
-
log label, hOptions
|
190
|
-
if (nArgs==2)
|
191
|
-
# --- don't repeat the label
|
192
|
-
logItem undef, item, hOptions
|
193
|
-
when 'string'
|
194
|
-
if (nArgs==2)
|
195
|
-
logItem label, item, hOptions
|
196
|
-
else
|
197
|
-
log label, hOptions
|
198
|
-
|
199
|
-
if hEnv
|
200
|
-
orgDebugging = debugging
|
201
|
-
{debugging, shouldLogFunc, shouldLogString} = hEnv
|
202
|
-
if doDebugDebug
|
203
|
-
trans = "#{orgDebugging} => #{debugging}"
|
204
|
-
LOG " Restore hEnv: debugging: #{trans}"
|
205
|
-
return true # allow use in boolean expressions
|
268
|
+
else if (nObjects > 0)
|
269
|
+
return ['objects', undef]
|
270
|
+
else
|
271
|
+
return ['string', undef]
|
206
272
|
|
207
273
|
# ---------------------------------------------------------------------------
|
208
274
|
|