@jdeighan/coffee-utils 7.0.51 → 7.0.54
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +2 -2
- package/src/call_stack.coffee +67 -15
- package/src/call_stack.js +62 -15
- package/src/debug_utils.coffee +185 -107
- package/src/debug_utils.js +190 -104
- package/src/log_utils.coffee +2 -2
- package/src/log_utils.js +2 -2
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@jdeighan/coffee-utils",
|
3
3
|
"type": "module",
|
4
|
-
"version": "7.0.
|
4
|
+
"version": "7.0.54",
|
5
5
|
"description": "A set of utility functions for CoffeeScript",
|
6
6
|
"main": "coffee_utils.js",
|
7
7
|
"exports": {
|
@@ -52,6 +52,6 @@
|
|
52
52
|
"svelte": "^3.48.0"
|
53
53
|
},
|
54
54
|
"devDependencies": {
|
55
|
-
"@jdeighan/unit-tester": "^2.0.
|
55
|
+
"@jdeighan/unit-tester": "^2.0.6"
|
56
56
|
}
|
57
57
|
}
|
package/src/call_stack.coffee
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# call_stack.coffee
|
2
2
|
|
3
3
|
import {
|
4
|
-
undef, defined, croak, assert, isBoolean, escapeStr,
|
4
|
+
undef, defined, croak, assert, OL, isBoolean, escapeStr,
|
5
5
|
} from '@jdeighan/coffee-utils'
|
6
6
|
import {log, LOG} from '@jdeighan/coffee-utils/log'
|
7
7
|
import {getPrefix} from '@jdeighan/coffee-utils/arrow'
|
@@ -36,14 +36,64 @@ export class CallStack
|
|
36
36
|
|
37
37
|
# ........................................................................
|
38
38
|
|
39
|
-
enter: (funcName,
|
39
|
+
enter: (funcName, oldFlag=undef) ->
|
40
|
+
# --- funcName might be <object>.<method>
|
40
41
|
|
42
|
+
assert (oldFlag == undef), "enter() takes only 1 arg"
|
41
43
|
if doDebugStack
|
42
|
-
LOG "[-->
|
44
|
+
LOG "[--> ENTER #{funcName}]"
|
45
|
+
|
46
|
+
lMatches = funcName.match(///^
|
47
|
+
([A-Za-z_][A-Za-z0-9_]*)
|
48
|
+
(?:
|
49
|
+
\.
|
50
|
+
([A-Za-z_][A-Za-z0-9_]*)
|
51
|
+
)?
|
52
|
+
$///)
|
53
|
+
assert defined(lMatches), "Bad funcName: #{OL(funcName)}"
|
54
|
+
[_, ident1, ident2] = lMatches
|
55
|
+
if ident2
|
56
|
+
@lStack.push({
|
57
|
+
fullName: "#{ident1}.#{ident2}"
|
58
|
+
funcName: ident2
|
59
|
+
isLogged: false
|
60
|
+
})
|
61
|
+
else
|
62
|
+
@lStack.push({
|
63
|
+
fullName: ident1
|
64
|
+
funcName: ident1
|
65
|
+
isLogged: false
|
66
|
+
})
|
67
|
+
return
|
68
|
+
|
69
|
+
# ........................................................................
|
70
|
+
|
71
|
+
isLogging: () ->
|
72
|
+
|
73
|
+
if (@lStack.length == 0)
|
74
|
+
return false
|
75
|
+
else
|
76
|
+
return @lStack[@lStack.length - 1].isLogged
|
77
|
+
|
78
|
+
# ........................................................................
|
79
|
+
|
80
|
+
isLoggingPrev: () ->
|
81
|
+
|
82
|
+
if (@lStack.length < 2)
|
83
|
+
return false
|
84
|
+
else
|
85
|
+
return @lStack[@lStack.length - 2].isLogged
|
86
|
+
|
87
|
+
# ........................................................................
|
88
|
+
|
89
|
+
logCurFunc: () ->
|
43
90
|
|
44
|
-
|
45
|
-
|
46
|
-
|
91
|
+
# --- funcName must be the current function
|
92
|
+
# and the isLogged flag must currently be false
|
93
|
+
cur = @lStack[@lStack.length - 1]
|
94
|
+
assert (cur.isLogged == false), "isLogged is already true"
|
95
|
+
cur.isLogged = true
|
96
|
+
@level += 1
|
47
97
|
return
|
48
98
|
|
49
99
|
# ........................................................................
|
@@ -58,18 +108,18 @@ export class CallStack
|
|
58
108
|
LOG "ERROR: returnFrom('#{funcName}') but stack is empty"
|
59
109
|
return
|
60
110
|
|
61
|
-
{
|
111
|
+
{fullName, isLogged} = @lStack.pop()
|
62
112
|
if isLogged && (@level > 0)
|
63
113
|
@level -= 1
|
64
114
|
|
65
115
|
# --- This should do nothing
|
66
|
-
while (
|
67
|
-
LOG "[MISSING RETURN FROM #{
|
68
|
-
{
|
116
|
+
while (fullName != fName) && (@lStack.length > 0)
|
117
|
+
LOG "[MISSING RETURN FROM #{fullName} (return from #{fName})]"
|
118
|
+
{fullName, isLogged} = @lStack.pop()
|
69
119
|
if isLogged && (@level > 0)
|
70
120
|
@level -= 1
|
71
121
|
|
72
|
-
if
|
122
|
+
if fullName != fName
|
73
123
|
@dump()
|
74
124
|
LOG "BAD BAD BAD BAD returnFrom('#{fName}')"
|
75
125
|
return
|
@@ -91,22 +141,24 @@ export class CallStack
|
|
91
141
|
|
92
142
|
# ........................................................................
|
93
143
|
|
94
|
-
isActive: (
|
144
|
+
isActive: (funcName) ->
|
145
|
+
# --- funcName won't be <obj>.<method>
|
146
|
+
# but the stack might contain that form
|
95
147
|
|
96
148
|
for h in @lStack
|
97
|
-
if (h.funcName ==
|
149
|
+
if (h.funcName == funcName)
|
98
150
|
return true
|
99
151
|
return false
|
100
152
|
|
101
153
|
# ........................................................................
|
102
154
|
# ........................................................................
|
103
155
|
|
104
|
-
dump: (label='CALL STACK') ->
|
156
|
+
dump: (prefix='', label='CALL STACK') ->
|
105
157
|
|
106
158
|
LOG "#{label}:"
|
107
159
|
if @lStack.length == 0
|
108
160
|
LOG " <EMPTY>"
|
109
161
|
else
|
110
162
|
for item, i in @lStack
|
111
|
-
LOG " #{i}: #{
|
163
|
+
LOG " #{i}: #{item.fullName} #{item.isLogged}"
|
112
164
|
return
|
package/src/call_stack.js
CHANGED
@@ -7,6 +7,7 @@ import {
|
|
7
7
|
defined,
|
8
8
|
croak,
|
9
9
|
assert,
|
10
|
+
OL,
|
10
11
|
isBoolean,
|
11
12
|
escapeStr
|
12
13
|
} from '@jdeighan/coffee-utils';
|
@@ -44,20 +45,64 @@ export var CallStack = class CallStack {
|
|
44
45
|
}
|
45
46
|
|
46
47
|
// ........................................................................
|
47
|
-
enter(funcName,
|
48
|
+
enter(funcName, oldFlag = undef) {
|
49
|
+
var _, ident1, ident2, lMatches;
|
50
|
+
// --- funcName might be <object>.<method>
|
51
|
+
assert(oldFlag === undef, "enter() takes only 1 arg");
|
48
52
|
if (doDebugStack) {
|
49
|
-
LOG(`[-->
|
53
|
+
LOG(`[--> ENTER ${funcName}]`);
|
50
54
|
}
|
51
|
-
|
52
|
-
|
53
|
-
|
55
|
+
lMatches = funcName.match(/^([A-Za-z_][A-Za-z0-9_]*)(?:\.([A-Za-z_][A-Za-z0-9_]*))?$/);
|
56
|
+
assert(defined(lMatches), `Bad funcName: ${OL(funcName)}`);
|
57
|
+
[_, ident1, ident2] = lMatches;
|
58
|
+
if (ident2) {
|
59
|
+
this.lStack.push({
|
60
|
+
fullName: `${ident1}.${ident2}`,
|
61
|
+
funcName: ident2,
|
62
|
+
isLogged: false
|
63
|
+
});
|
64
|
+
} else {
|
65
|
+
this.lStack.push({
|
66
|
+
fullName: ident1,
|
67
|
+
funcName: ident1,
|
68
|
+
isLogged: false
|
69
|
+
});
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
// ........................................................................
|
74
|
+
isLogging() {
|
75
|
+
if (this.lStack.length === 0) {
|
76
|
+
return false;
|
77
|
+
} else {
|
78
|
+
return this.lStack[this.lStack.length - 1].isLogged;
|
54
79
|
}
|
55
80
|
}
|
56
81
|
|
82
|
+
// ........................................................................
|
83
|
+
isLoggingPrev() {
|
84
|
+
if (this.lStack.length < 2) {
|
85
|
+
return false;
|
86
|
+
} else {
|
87
|
+
return this.lStack[this.lStack.length - 2].isLogged;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
// ........................................................................
|
92
|
+
logCurFunc() {
|
93
|
+
var cur;
|
94
|
+
// --- funcName must be the current function
|
95
|
+
// and the isLogged flag must currently be false
|
96
|
+
cur = this.lStack[this.lStack.length - 1];
|
97
|
+
assert(cur.isLogged === false, "isLogged is already true");
|
98
|
+
cur.isLogged = true;
|
99
|
+
this.level += 1;
|
100
|
+
}
|
101
|
+
|
57
102
|
// ........................................................................
|
58
103
|
// --- if stack is empty, log the error, but continue
|
59
104
|
returnFrom(fName) {
|
60
|
-
var
|
105
|
+
var fullName, isLogged;
|
61
106
|
if (doDebugStack) {
|
62
107
|
LOG(`[<-- BACK ${fName}]`);
|
63
108
|
}
|
@@ -65,19 +110,19 @@ export var CallStack = class CallStack {
|
|
65
110
|
LOG(`ERROR: returnFrom('${funcName}') but stack is empty`);
|
66
111
|
return;
|
67
112
|
}
|
68
|
-
({
|
113
|
+
({fullName, isLogged} = this.lStack.pop());
|
69
114
|
if (isLogged && (this.level > 0)) {
|
70
115
|
this.level -= 1;
|
71
116
|
}
|
72
117
|
// --- This should do nothing
|
73
|
-
while ((
|
74
|
-
LOG(`[MISSING RETURN FROM ${
|
75
|
-
({
|
118
|
+
while ((fullName !== fName) && (this.lStack.length > 0)) {
|
119
|
+
LOG(`[MISSING RETURN FROM ${fullName} (return from ${fName})]`);
|
120
|
+
({fullName, isLogged} = this.lStack.pop());
|
76
121
|
if (isLogged && (this.level > 0)) {
|
77
122
|
this.level -= 1;
|
78
123
|
}
|
79
124
|
}
|
80
|
-
if (
|
125
|
+
if (fullName !== fName) {
|
81
126
|
this.dump();
|
82
127
|
LOG(`BAD BAD BAD BAD returnFrom('${fName}')`);
|
83
128
|
}
|
@@ -98,12 +143,14 @@ export var CallStack = class CallStack {
|
|
98
143
|
}
|
99
144
|
|
100
145
|
// ........................................................................
|
101
|
-
isActive(
|
146
|
+
isActive(funcName) {
|
102
147
|
var h, j, len, ref;
|
103
148
|
ref = this.lStack;
|
149
|
+
// --- funcName won't be <obj>.<method>
|
150
|
+
// but the stack might contain that form
|
104
151
|
for (j = 0, len = ref.length; j < len; j++) {
|
105
152
|
h = ref[j];
|
106
|
-
if (h.funcName ===
|
153
|
+
if (h.funcName === funcName) {
|
107
154
|
return true;
|
108
155
|
}
|
109
156
|
}
|
@@ -112,7 +159,7 @@ export var CallStack = class CallStack {
|
|
112
159
|
|
113
160
|
// ........................................................................
|
114
161
|
// ........................................................................
|
115
|
-
dump(label = 'CALL STACK') {
|
162
|
+
dump(prefix = '', label = 'CALL STACK') {
|
116
163
|
var i, item, j, len, ref;
|
117
164
|
LOG(`${label}:`);
|
118
165
|
if (this.lStack.length === 0) {
|
@@ -121,7 +168,7 @@ export var CallStack = class CallStack {
|
|
121
168
|
ref = this.lStack;
|
122
169
|
for (i = j = 0, len = ref.length; j < len; i = ++j) {
|
123
170
|
item = ref[i];
|
124
|
-
LOG(` ${i}: ${
|
171
|
+
LOG(` ${i}: ${item.fullName} ${item.isLogged}`);
|
125
172
|
}
|
126
173
|
}
|
127
174
|
}
|
package/src/debug_utils.coffee
CHANGED
@@ -18,7 +18,130 @@ import {
|
|
18
18
|
|
19
19
|
callStack = new CallStack()
|
20
20
|
doDebugDebug = false
|
21
|
-
|
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 && (label.indexOf('call') == -1)
|
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
|
+
|
123
|
+
if doDebugDebug
|
124
|
+
LOG "stdShouldLog(#{OL(label)}, #{OL(type)}, #{OL(funcName)}, stack)"
|
125
|
+
LOG "stack", stack
|
126
|
+
LOG "lFuncList", lFuncList
|
127
|
+
|
128
|
+
switch type
|
129
|
+
when 'enter'
|
130
|
+
if funcMatch(stack, lFuncList)
|
131
|
+
return label
|
132
|
+
|
133
|
+
else
|
134
|
+
# --- As a special case, if we enter a function where we will not
|
135
|
+
# be logging, but we were logging in the calling function,
|
136
|
+
# we'll log out the call itself
|
137
|
+
|
138
|
+
prevLogged = stack.isLoggingPrev()
|
139
|
+
if prevLogged
|
140
|
+
return label.replace('enter', 'call')
|
141
|
+
else
|
142
|
+
if funcMatch(stack, lFuncList)
|
143
|
+
return label
|
144
|
+
return undef
|
22
145
|
|
23
146
|
# ---------------------------------------------------------------------------
|
24
147
|
|
@@ -36,7 +159,7 @@ resetDebugging = () ->
|
|
36
159
|
if doDebugDebug
|
37
160
|
LOG "resetDebugging()"
|
38
161
|
callStack.reset()
|
39
|
-
shouldLog = (type,
|
162
|
+
shouldLog = (label, type, funcName, stack) -> undef
|
40
163
|
return
|
41
164
|
|
42
165
|
# ---------------------------------------------------------------------------
|
@@ -45,44 +168,82 @@ export setDebugging = (option) ->
|
|
45
168
|
|
46
169
|
resetDebugging()
|
47
170
|
if isBoolean(option)
|
48
|
-
|
171
|
+
if option
|
172
|
+
shouldLog = (label, type, funcName, stack) -> label
|
173
|
+
else
|
174
|
+
shouldLog = (label, type, funcName, stack) -> undef
|
175
|
+
if doDebugDebug
|
176
|
+
LOG "setDebugging = #{option}"
|
49
177
|
else if isString(option)
|
50
|
-
|
51
|
-
|
52
|
-
switch type
|
53
|
-
when 'enter'
|
54
|
-
return funcMatch(stack, lFuncs, str)
|
55
|
-
else
|
56
|
-
return funcMatch(stack, lFuncs)
|
178
|
+
lFuncList = getFuncList(option)
|
179
|
+
shouldLog = stdShouldLog
|
57
180
|
if doDebugDebug
|
58
181
|
LOG "setDebugging FUNCS: #{option}"
|
182
|
+
LOG 'lFuncList', lFuncList
|
59
183
|
else if isFunction(option)
|
60
184
|
shouldLog = option
|
61
185
|
if doDebugDebug
|
62
186
|
LOG "setDebugging to custom func"
|
63
187
|
else
|
64
|
-
croak "
|
188
|
+
croak "bad parameter #{OL(option)}"
|
65
189
|
return
|
66
190
|
|
67
191
|
# ---------------------------------------------------------------------------
|
68
192
|
# --- export only to allow unit tests
|
69
193
|
|
70
|
-
export
|
194
|
+
export getFuncList = (str) ->
|
195
|
+
|
196
|
+
lFuncList = []
|
197
|
+
for word in words(str)
|
198
|
+
if lMatches = word.match(///^
|
199
|
+
([A-Za-z_][A-Za-z0-9_]*)
|
200
|
+
(?:
|
201
|
+
\.
|
202
|
+
([A-Za-z_][A-Za-z0-9_]*)
|
203
|
+
)?
|
204
|
+
(\+)?
|
205
|
+
$///)
|
206
|
+
[_, ident1, ident2, plus] = lMatches
|
207
|
+
if ident2
|
208
|
+
lFuncList.push {
|
209
|
+
name: ident2
|
210
|
+
object: ident1
|
211
|
+
plus: (plus == '+')
|
212
|
+
}
|
213
|
+
else
|
214
|
+
lFuncList.push {
|
215
|
+
name: ident1
|
216
|
+
plus: (plus == '+')
|
217
|
+
}
|
218
|
+
else
|
219
|
+
croak "Bad word in func list: #{OL(word)}"
|
220
|
+
return lFuncList
|
221
|
+
|
222
|
+
# ---------------------------------------------------------------------------
|
223
|
+
# --- export only to allow unit tests
|
71
224
|
|
72
|
-
|
73
|
-
|
225
|
+
export funcMatch = (stack, lFuncList) ->
|
226
|
+
|
227
|
+
assert isArray(lFuncList), "not an array #{OL(lFuncList)}"
|
74
228
|
|
75
229
|
curFunc = stack.curFunc()
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
230
|
+
if doDebugDebug
|
231
|
+
LOG "funcMatch(): curFunc = #{OL(curFunc)}"
|
232
|
+
stack.dump(' ')
|
233
|
+
LOG 'lFuncList', lFuncList
|
234
|
+
for h in lFuncList
|
235
|
+
{name, object, plus} = h
|
236
|
+
if (name == curFunc)
|
237
|
+
if doDebugDebug
|
238
|
+
LOG " curFunc in lFuncList - match successful"
|
239
|
+
return true
|
240
|
+
if plus && stack.isActive(name)
|
241
|
+
if doDebugDebug
|
242
|
+
LOG " func #{OL(name)} is active - match successful"
|
243
|
+
return true
|
244
|
+
if doDebugDebug
|
245
|
+
LOG " - no match"
|
246
|
+
return false
|
86
247
|
|
87
248
|
# ---------------------------------------------------------------------------
|
88
249
|
# --- type is one of: 'enter', 'return', 'string', 'object'
|
@@ -116,89 +277,6 @@ export getType = (str, nObjects) ->
|
|
116
277
|
|
117
278
|
# ---------------------------------------------------------------------------
|
118
279
|
|
119
|
-
export debug = (label, lObjects...) ->
|
120
|
-
|
121
|
-
assert isString(label), "1st arg #{OL(label)} should be a string"
|
122
|
-
|
123
|
-
# --- We want to allow objects to be undef. Therefore, we need to
|
124
|
-
# distinguish between 1 arg sent vs. 2 or more args sent
|
125
|
-
nObjects = lObjects.length
|
126
|
-
|
127
|
-
# --- funcName is only set for types 'enter' and 'return'
|
128
|
-
[type, funcName] = getType(label, nObjects)
|
129
|
-
switch type
|
130
|
-
when 'enter'
|
131
|
-
doLog = shouldLog(type, funcName, callStack)
|
132
|
-
|
133
|
-
# --- If we won't be logging when funcName is activated
|
134
|
-
# then change 'enter' to 'call'
|
135
|
-
callStack.enter funcName # add to call stack
|
136
|
-
if ! shouldLog('string', 'abc', callStack)
|
137
|
-
label = label.replace('enter', 'call')
|
138
|
-
callStack.returnFrom funcName # remove from call stack
|
139
|
-
when 'return'
|
140
|
-
doLog = shouldLog(type, funcName, callStack)
|
141
|
-
when 'string'
|
142
|
-
doLog = shouldLog(type, label, callStack)
|
143
|
-
assert (nObjects == 0),
|
144
|
-
"multiple objects only not allowed for #{OL(type)}"
|
145
|
-
when 'objects'
|
146
|
-
doLog = shouldLog(type, label, callStack)
|
147
|
-
assert (nObjects > 0),
|
148
|
-
"multiple objects only not allowed for #{OL(type)}"
|
149
|
-
|
150
|
-
if doDebugDebug
|
151
|
-
if nObjects == 0
|
152
|
-
LOG "debug(#{OL(label)}) - 1 arg"
|
153
|
-
else
|
154
|
-
LOG "debug(#{OL(label)}), #{nObjects} args"
|
155
|
-
LOG "doLog = #{OL(doLog)}"
|
156
|
-
LOG "type = #{OL(type)}"
|
157
|
-
LOG "funcName = #{OL(funcName)}"
|
158
|
-
|
159
|
-
if doLog
|
160
|
-
level = callStack.getLevel()
|
161
|
-
prefix = getPrefix(level)
|
162
|
-
|
163
|
-
if doDebugDebug
|
164
|
-
LOG "callStack", callStack
|
165
|
-
LOG "level = #{OL(level)}"
|
166
|
-
LOG "prefix = #{OL(prefix)}"
|
167
|
-
|
168
|
-
switch type
|
169
|
-
when 'enter'
|
170
|
-
log label, {prefix}
|
171
|
-
for obj,i in lObjects
|
172
|
-
if (i > 0)
|
173
|
-
log sep_dash, {prefix: removeLastVbar(prefix)}
|
174
|
-
logItem undef, obj, {prefix: removeLastVbar(prefix)}
|
175
|
-
when 'return'
|
176
|
-
log label, {prefix: addArrow(prefix)}
|
177
|
-
for obj,i in lObjects
|
178
|
-
if (i > 0)
|
179
|
-
log sep_dash, {prefix: removeLastVbar(prefix)}
|
180
|
-
logItem undef, obj, {prefix: removeLastVbar(prefix)}
|
181
|
-
when 'string'
|
182
|
-
log label, {prefix}
|
183
|
-
when 'objects'
|
184
|
-
if (nObjects==1) && shortEnough(label, lObjects[0])
|
185
|
-
logItem label, lObjects[0], {prefix}
|
186
|
-
else
|
187
|
-
if (label.indexOf(':') != label.length - 1)
|
188
|
-
label += ':'
|
189
|
-
log label, {prefix}
|
190
|
-
for obj in lObjects
|
191
|
-
logItem undef, obj, {prefix}
|
192
|
-
|
193
|
-
if (type == 'enter')
|
194
|
-
callStack.enter funcName, doLog
|
195
|
-
else if (type == 'return')
|
196
|
-
callStack.returnFrom funcName
|
197
|
-
|
198
|
-
return true # allow use in boolean expressions
|
199
|
-
|
200
|
-
# ---------------------------------------------------------------------------
|
201
|
-
|
202
280
|
reMethod = ///^
|
203
281
|
([A-Za-z_][A-Za-z0-9_]*)
|
204
282
|
\.
|
package/src/debug_utils.js
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
// Generated by CoffeeScript 2.7.0
|
2
|
-
|
3
|
-
var callStack, doDebugDebug, reMethod, resetDebugging
|
4
|
-
indexOf = [].indexOf;
|
2
|
+
// debug_utils.coffee
|
3
|
+
var callStack, doDebugDebug, reMethod, resetDebugging;
|
5
4
|
|
6
5
|
import {
|
7
6
|
assert,
|
@@ -55,93 +54,9 @@ callStack = new CallStack();
|
|
55
54
|
|
56
55
|
doDebugDebug = false;
|
57
56
|
|
58
|
-
shouldLog = undef; // set in resetDebugging() and setDebugging()
|
57
|
+
export var shouldLog = undef; // set in resetDebugging() and setDebugging()
|
59
58
|
|
60
|
-
|
61
|
-
// ---------------------------------------------------------------------------
|
62
|
-
export var debugDebug = function(flag = true) {
|
63
|
-
doDebugDebug = flag;
|
64
|
-
if (doDebugDebug) {
|
65
|
-
LOG(`doDebugDebug = ${flag}`);
|
66
|
-
}
|
67
|
-
};
|
68
|
-
|
69
|
-
// ---------------------------------------------------------------------------
|
70
|
-
resetDebugging = function() {
|
71
|
-
if (doDebugDebug) {
|
72
|
-
LOG("resetDebugging()");
|
73
|
-
}
|
74
|
-
callStack.reset();
|
75
|
-
shouldLog = function(type, str, stack) {
|
76
|
-
return false;
|
77
|
-
};
|
78
|
-
};
|
79
|
-
|
80
|
-
// ---------------------------------------------------------------------------
|
81
|
-
export var setDebugging = function(option) {
|
82
|
-
resetDebugging();
|
83
|
-
if (isBoolean(option)) {
|
84
|
-
shouldLog = function(type, str, stack) {
|
85
|
-
return option;
|
86
|
-
};
|
87
|
-
} else if (isString(option)) {
|
88
|
-
shouldLog = function(type, str, stack) {
|
89
|
-
var lFuncs;
|
90
|
-
lFuncs = words(option);
|
91
|
-
switch (type) {
|
92
|
-
case 'enter':
|
93
|
-
return funcMatch(stack, lFuncs, str);
|
94
|
-
default:
|
95
|
-
return funcMatch(stack, lFuncs);
|
96
|
-
}
|
97
|
-
};
|
98
|
-
if (doDebugDebug) {
|
99
|
-
LOG(`setDebugging FUNCS: ${option}`);
|
100
|
-
}
|
101
|
-
} else if (isFunction(option)) {
|
102
|
-
shouldLog = option;
|
103
|
-
if (doDebugDebug) {
|
104
|
-
LOG("setDebugging to custom func");
|
105
|
-
}
|
106
|
-
} else {
|
107
|
-
croak(`setDebugging(): bad parameter ${OL(option)}`);
|
108
|
-
}
|
109
|
-
};
|
110
|
-
|
111
|
-
// ---------------------------------------------------------------------------
|
112
|
-
// --- export only to allow unit tests
|
113
|
-
export var funcMatch = function(stack, lFuncNames, enteringFunc = undef) {
|
114
|
-
var _, cls, curFunc, lMatches, meth;
|
115
|
-
if (defined(enteringFunc) && (indexOf.call(lFuncNames, enteringFunc) >= 0)) {
|
116
|
-
return true;
|
117
|
-
}
|
118
|
-
curFunc = stack.curFunc();
|
119
|
-
assert(isString(curFunc), `funcMatch(): not a string ${OL(curFunc)}`);
|
120
|
-
assert(isArray(lFuncNames), `funcMatch(): bad array ${lFuncNames}`);
|
121
|
-
if (lFuncNames.includes(curFunc)) {
|
122
|
-
return true;
|
123
|
-
} else if ((lMatches = curFunc.match(reMethod)) && ([_, cls, meth] = lMatches) && lFuncNames.includes(meth)) {
|
124
|
-
return true;
|
125
|
-
} else {
|
126
|
-
return false;
|
127
|
-
}
|
128
|
-
};
|
129
|
-
|
130
|
-
// ---------------------------------------------------------------------------
|
131
|
-
// --- type is one of: 'enter', 'return', 'string', 'object'
|
132
|
-
export var getType = function(str, nObjects) {
|
133
|
-
var lMatches;
|
134
|
-
if (lMatches = str.match(/^\s*enter\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
|
135
|
-
// --- We are entering function curFunc
|
136
|
-
return ['enter', lMatches[1]];
|
137
|
-
} else if (lMatches = str.match(/^\s*return.+from\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
|
138
|
-
return ['return', lMatches[1]];
|
139
|
-
} else if (nObjects > 0) {
|
140
|
-
return ['objects', undef];
|
141
|
-
} else {
|
142
|
-
return ['string', undef];
|
143
|
-
}
|
144
|
-
};
|
59
|
+
export var lFuncList = [];
|
145
60
|
|
146
61
|
// ---------------------------------------------------------------------------
|
147
62
|
export var debug = function(label, ...lObjects) {
|
@@ -152,28 +67,27 @@ export var debug = function(label, ...lObjects) {
|
|
152
67
|
nObjects = lObjects.length;
|
153
68
|
// --- funcName is only set for types 'enter' and 'return'
|
154
69
|
[type, funcName] = getType(label, nObjects);
|
70
|
+
if (doDebugDebug) {
|
71
|
+
LOG(`debug(): type = ${OL(type)}`);
|
72
|
+
LOG(`debug(): funcName = ${OL(funcName)}`);
|
73
|
+
}
|
155
74
|
switch (type) {
|
156
75
|
case 'enter':
|
157
|
-
|
158
|
-
|
159
|
-
// then change 'enter' to 'call'
|
160
|
-
callStack.enter(funcName); // add to call stack
|
161
|
-
if (!shouldLog('string', 'abc', callStack)) {
|
162
|
-
label = label.replace('enter', 'call');
|
163
|
-
}
|
164
|
-
callStack.returnFrom(funcName); // remove from call stack
|
76
|
+
callStack.enter(funcName);
|
77
|
+
label = shouldLog(label, type, funcName, callStack);
|
165
78
|
break;
|
166
79
|
case 'return':
|
167
|
-
|
80
|
+
label = shouldLog(label, type, funcName, callStack);
|
168
81
|
break;
|
169
82
|
case 'string':
|
170
|
-
|
83
|
+
label = shouldLog(label, type, undef, callStack);
|
171
84
|
assert(nObjects === 0, `multiple objects only not allowed for ${OL(type)}`);
|
172
85
|
break;
|
173
86
|
case 'objects':
|
174
|
-
|
87
|
+
label = shouldLog(label, type, undef, callStack);
|
175
88
|
assert(nObjects > 0, `multiple objects only not allowed for ${OL(type)}`);
|
176
89
|
}
|
90
|
+
doLog = defined(label);
|
177
91
|
if (doDebugDebug) {
|
178
92
|
if (nObjects === 0) {
|
179
93
|
LOG(`debug(${OL(label)}) - 1 arg`);
|
@@ -181,8 +95,6 @@ export var debug = function(label, ...lObjects) {
|
|
181
95
|
LOG(`debug(${OL(label)}), ${nObjects} args`);
|
182
96
|
}
|
183
97
|
LOG(`doLog = ${OL(doLog)}`);
|
184
|
-
LOG(`type = ${OL(type)}`);
|
185
|
-
LOG(`funcName = ${OL(funcName)}`);
|
186
98
|
}
|
187
99
|
if (doLog) {
|
188
100
|
level = callStack.getLevel();
|
@@ -241,8 +153,8 @@ export var debug = function(label, ...lObjects) {
|
|
241
153
|
}
|
242
154
|
}
|
243
155
|
}
|
244
|
-
if (type === 'enter') {
|
245
|
-
callStack.
|
156
|
+
if ((type === 'enter') && doLog && (label.indexOf('call') === -1)) {
|
157
|
+
callStack.logCurFunc();
|
246
158
|
} else if (type === 'return') {
|
247
159
|
callStack.returnFrom(funcName);
|
248
160
|
}
|
@@ -250,6 +162,180 @@ export var debug = function(label, ...lObjects) {
|
|
250
162
|
};
|
251
163
|
|
252
164
|
|
165
|
+
// ---------------------------------------------------------------------------
|
166
|
+
export var stdShouldLog = function(label, type, funcName, stack) {
|
167
|
+
var prevLogged;
|
168
|
+
// --- if type is 'enter', then funcName won't be on the stack yet
|
169
|
+
// returns the (possibly modified) label to log
|
170
|
+
|
171
|
+
// --- If we're logging now,
|
172
|
+
// but we won't be logging when funcName is activated
|
173
|
+
// then change 'enter' to 'call'
|
174
|
+
assert(isString(label), `label ${OL(label)} not a string`);
|
175
|
+
assert(isString(type), `type ${OL(type)} not a string`);
|
176
|
+
if ((type === 'enter') || (type === 'return')) {
|
177
|
+
assert(isString(funcName), `func name ${OL(funcName)} not a string`);
|
178
|
+
} else {
|
179
|
+
assert(funcName === undef, `func name ${OL(funcName)} not undef`);
|
180
|
+
}
|
181
|
+
assert(stack instanceof CallStack, "not a call stack object");
|
182
|
+
if (doDebugDebug) {
|
183
|
+
LOG(`stdShouldLog(${OL(label)}, ${OL(type)}, ${OL(funcName)}, stack)`);
|
184
|
+
LOG("stack", stack);
|
185
|
+
LOG("lFuncList", lFuncList);
|
186
|
+
}
|
187
|
+
switch (type) {
|
188
|
+
case 'enter':
|
189
|
+
if (funcMatch(stack, lFuncList)) {
|
190
|
+
return label;
|
191
|
+
} else {
|
192
|
+
// --- As a special case, if we enter a function where we will not
|
193
|
+
// be logging, but we were logging in the calling function,
|
194
|
+
// we'll log out the call itself
|
195
|
+
prevLogged = stack.isLoggingPrev();
|
196
|
+
if (prevLogged) {
|
197
|
+
return label.replace('enter', 'call');
|
198
|
+
}
|
199
|
+
}
|
200
|
+
break;
|
201
|
+
default:
|
202
|
+
if (funcMatch(stack, lFuncList)) {
|
203
|
+
return label;
|
204
|
+
}
|
205
|
+
}
|
206
|
+
return undef;
|
207
|
+
};
|
208
|
+
|
209
|
+
// ---------------------------------------------------------------------------
|
210
|
+
export var debugDebug = function(flag = true) {
|
211
|
+
doDebugDebug = flag;
|
212
|
+
if (doDebugDebug) {
|
213
|
+
LOG(`doDebugDebug = ${flag}`);
|
214
|
+
}
|
215
|
+
};
|
216
|
+
|
217
|
+
// ---------------------------------------------------------------------------
|
218
|
+
resetDebugging = function() {
|
219
|
+
if (doDebugDebug) {
|
220
|
+
LOG("resetDebugging()");
|
221
|
+
}
|
222
|
+
callStack.reset();
|
223
|
+
shouldLog = function(label, type, funcName, stack) {
|
224
|
+
return undef;
|
225
|
+
};
|
226
|
+
};
|
227
|
+
|
228
|
+
// ---------------------------------------------------------------------------
|
229
|
+
export var setDebugging = function(option) {
|
230
|
+
resetDebugging();
|
231
|
+
if (isBoolean(option)) {
|
232
|
+
if (option) {
|
233
|
+
shouldLog = function(label, type, funcName, stack) {
|
234
|
+
return label;
|
235
|
+
};
|
236
|
+
} else {
|
237
|
+
shouldLog = function(label, type, funcName, stack) {
|
238
|
+
return undef;
|
239
|
+
};
|
240
|
+
}
|
241
|
+
if (doDebugDebug) {
|
242
|
+
LOG(`setDebugging = ${option}`);
|
243
|
+
}
|
244
|
+
} else if (isString(option)) {
|
245
|
+
lFuncList = getFuncList(option);
|
246
|
+
shouldLog = stdShouldLog;
|
247
|
+
if (doDebugDebug) {
|
248
|
+
LOG(`setDebugging FUNCS: ${option}`);
|
249
|
+
LOG('lFuncList', lFuncList);
|
250
|
+
}
|
251
|
+
} else if (isFunction(option)) {
|
252
|
+
shouldLog = option;
|
253
|
+
if (doDebugDebug) {
|
254
|
+
LOG("setDebugging to custom func");
|
255
|
+
}
|
256
|
+
} else {
|
257
|
+
croak(`bad parameter ${OL(option)}`);
|
258
|
+
}
|
259
|
+
};
|
260
|
+
|
261
|
+
// ---------------------------------------------------------------------------
|
262
|
+
// --- export only to allow unit tests
|
263
|
+
export var getFuncList = function(str) {
|
264
|
+
var _, ident1, ident2, j, lMatches, len1, plus, ref, word;
|
265
|
+
lFuncList = [];
|
266
|
+
ref = words(str);
|
267
|
+
for (j = 0, len1 = ref.length; j < len1; j++) {
|
268
|
+
word = ref[j];
|
269
|
+
if (lMatches = word.match(/^([A-Za-z_][A-Za-z0-9_]*)(?:\.([A-Za-z_][A-Za-z0-9_]*))?(\+)?$/)) {
|
270
|
+
[_, ident1, ident2, plus] = lMatches;
|
271
|
+
if (ident2) {
|
272
|
+
lFuncList.push({
|
273
|
+
name: ident2,
|
274
|
+
object: ident1,
|
275
|
+
plus: plus === '+'
|
276
|
+
});
|
277
|
+
} else {
|
278
|
+
lFuncList.push({
|
279
|
+
name: ident1,
|
280
|
+
plus: plus === '+'
|
281
|
+
});
|
282
|
+
}
|
283
|
+
} else {
|
284
|
+
croak(`Bad word in func list: ${OL(word)}`);
|
285
|
+
}
|
286
|
+
}
|
287
|
+
return lFuncList;
|
288
|
+
};
|
289
|
+
|
290
|
+
// ---------------------------------------------------------------------------
|
291
|
+
// --- export only to allow unit tests
|
292
|
+
export var funcMatch = function(stack, lFuncList) {
|
293
|
+
var curFunc, h, j, len1, name, object, plus;
|
294
|
+
assert(isArray(lFuncList), `not an array ${OL(lFuncList)}`);
|
295
|
+
curFunc = stack.curFunc();
|
296
|
+
if (doDebugDebug) {
|
297
|
+
LOG(`funcMatch(): curFunc = ${OL(curFunc)}`);
|
298
|
+
stack.dump(' ');
|
299
|
+
LOG('lFuncList', lFuncList);
|
300
|
+
}
|
301
|
+
for (j = 0, len1 = lFuncList.length; j < len1; j++) {
|
302
|
+
h = lFuncList[j];
|
303
|
+
({name, object, plus} = h);
|
304
|
+
if (name === curFunc) {
|
305
|
+
if (doDebugDebug) {
|
306
|
+
LOG(" curFunc in lFuncList - match successful");
|
307
|
+
}
|
308
|
+
return true;
|
309
|
+
}
|
310
|
+
if (plus && stack.isActive(name)) {
|
311
|
+
if (doDebugDebug) {
|
312
|
+
LOG(` func ${OL(name)} is active - match successful`);
|
313
|
+
}
|
314
|
+
return true;
|
315
|
+
}
|
316
|
+
}
|
317
|
+
if (doDebugDebug) {
|
318
|
+
LOG(" - no match");
|
319
|
+
}
|
320
|
+
return false;
|
321
|
+
};
|
322
|
+
|
323
|
+
// ---------------------------------------------------------------------------
|
324
|
+
// --- type is one of: 'enter', 'return', 'string', 'object'
|
325
|
+
export var getType = function(str, nObjects) {
|
326
|
+
var lMatches;
|
327
|
+
if (lMatches = str.match(/^\s*enter\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
|
328
|
+
// --- We are entering function curFunc
|
329
|
+
return ['enter', lMatches[1]];
|
330
|
+
} else if (lMatches = str.match(/^\s*return.+from\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
|
331
|
+
return ['return', lMatches[1]];
|
332
|
+
} else if (nObjects > 0) {
|
333
|
+
return ['objects', undef];
|
334
|
+
} else {
|
335
|
+
return ['string', undef];
|
336
|
+
}
|
337
|
+
};
|
338
|
+
|
253
339
|
// ---------------------------------------------------------------------------
|
254
340
|
reMethod = /^([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)$/;
|
255
341
|
|
package/src/log_utils.coffee
CHANGED
@@ -36,9 +36,9 @@ export LOG = (lArgs...) ->
|
|
36
36
|
if lArgs.length > 1
|
37
37
|
# --- There's both a label and an item
|
38
38
|
if (item == undef)
|
39
|
-
console.log "#{label}
|
39
|
+
console.log "#{label} = undef"
|
40
40
|
else if (item == null)
|
41
|
-
console.log "#{label}
|
41
|
+
console.log "#{label} = null"
|
42
42
|
else
|
43
43
|
console.log sep_dash
|
44
44
|
console.log "#{label}:"
|
package/src/log_utils.js
CHANGED
@@ -55,9 +55,9 @@ export var LOG = function(...lArgs) {
|
|
55
55
|
if (lArgs.length > 1) {
|
56
56
|
// --- There's both a label and an item
|
57
57
|
if (item === undef) {
|
58
|
-
console.log(`${label}
|
58
|
+
console.log(`${label} = undef`);
|
59
59
|
} else if (item === null) {
|
60
|
-
console.log(`${label}
|
60
|
+
console.log(`${label} = null`);
|
61
61
|
} else {
|
62
62
|
console.log(sep_dash);
|
63
63
|
console.log(`${label}:`);
|