rflib-plugin 0.11.1 → 0.12.1
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.
|
@@ -15,7 +15,8 @@ class ApexInstrumentationService {
|
|
|
15
15
|
static IF_STATEMENT_REGEX = /if\s*\((.*?)\)\s*(?:{([^]*?(?:(?<!{){(?:[^]*?)}(?!})[^]*?)*)}|([^{].*?)(?=\s*(?:;|$));)/g;
|
|
16
16
|
static ELSE_REGEX = /\s*else(?!\s*if\b)\s*(?:{((?:[^{}]|{(?:[^{}]|{[^{}]*})*})*)}|([^{;]*(?:;|$)))/g;
|
|
17
17
|
static IS_INSTRUMENTED_REGEX = /(\brflib_Logger\b|\brflib_TestUtil\b)/;
|
|
18
|
-
static
|
|
18
|
+
static SYSTEM_DEBUG_START_REGEX = /System\.debug\s*\(/g;
|
|
19
|
+
static LOGGING_LEVEL_REGEX = /^LoggingLevel\.(\w+)\s*,\s*([\s\S]*)$/;
|
|
19
20
|
static PRIMITIVE_TYPES = new Set([
|
|
20
21
|
'STRING',
|
|
21
22
|
'INTEGER',
|
|
@@ -126,7 +127,86 @@ class ApexInstrumentationService {
|
|
|
126
127
|
return modified;
|
|
127
128
|
}
|
|
128
129
|
static processSystemDebugStatements(content, loggerName) {
|
|
129
|
-
|
|
130
|
+
const debugStartRegex = new RegExp(this.SYSTEM_DEBUG_START_REGEX);
|
|
131
|
+
let match;
|
|
132
|
+
let lastIndex = 0;
|
|
133
|
+
let output = '';
|
|
134
|
+
while ((match = debugStartRegex.exec(content)) !== null) {
|
|
135
|
+
output += content.substring(lastIndex, match.index);
|
|
136
|
+
const openParenIndex = match.index + match[0].length - 1;
|
|
137
|
+
let depth = 1;
|
|
138
|
+
let i = openParenIndex + 1;
|
|
139
|
+
let inString = false;
|
|
140
|
+
let isEscaped = false;
|
|
141
|
+
for (; i < content.length && depth > 0; i++) {
|
|
142
|
+
const char = content[i];
|
|
143
|
+
if (inString) {
|
|
144
|
+
if (isEscaped) {
|
|
145
|
+
isEscaped = false;
|
|
146
|
+
}
|
|
147
|
+
else if (char === '\\') {
|
|
148
|
+
isEscaped = true;
|
|
149
|
+
}
|
|
150
|
+
else if (char === "'") {
|
|
151
|
+
inString = false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else if (char === "'") {
|
|
155
|
+
inString = true;
|
|
156
|
+
}
|
|
157
|
+
else if (char === '(') {
|
|
158
|
+
depth++;
|
|
159
|
+
}
|
|
160
|
+
else if (char === ')') {
|
|
161
|
+
depth--;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (depth === 0) {
|
|
165
|
+
const closeParenIndex = i - 1;
|
|
166
|
+
const remaining = content.substring(closeParenIndex + 1);
|
|
167
|
+
const semiColonMatch = remaining.match(/^\s*;/);
|
|
168
|
+
if (semiColonMatch) {
|
|
169
|
+
const endOfStatement = closeParenIndex + 1 + semiColonMatch[0].length;
|
|
170
|
+
const args = content.substring(openParenIndex + 1, closeParenIndex);
|
|
171
|
+
const processed = this.transformSystemDebug(args, loggerName);
|
|
172
|
+
output += processed;
|
|
173
|
+
lastIndex = endOfStatement;
|
|
174
|
+
debugStartRegex.lastIndex = endOfStatement;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
output += match[0];
|
|
178
|
+
lastIndex = match.index + match[0].length;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
output += match[0];
|
|
183
|
+
lastIndex = match.index + match[0].length;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
output += content.substring(lastIndex);
|
|
187
|
+
return output;
|
|
188
|
+
}
|
|
189
|
+
static transformSystemDebug(args, loggerName) {
|
|
190
|
+
const trimmedArgs = args.trim();
|
|
191
|
+
const levelMatch = trimmedArgs.match(this.LOGGING_LEVEL_REGEX);
|
|
192
|
+
if (levelMatch) {
|
|
193
|
+
const level = levelMatch[1].toUpperCase();
|
|
194
|
+
const message = levelMatch[2].trim();
|
|
195
|
+
let method = 'debug';
|
|
196
|
+
if (level === 'ERROR') {
|
|
197
|
+
method = 'error';
|
|
198
|
+
}
|
|
199
|
+
else if (level === 'WARN') {
|
|
200
|
+
method = 'warn';
|
|
201
|
+
}
|
|
202
|
+
else if (level === 'INFO') {
|
|
203
|
+
method = 'info';
|
|
204
|
+
}
|
|
205
|
+
const formattedMessage = message.startsWith("'") ? message : `JSON.serialize(${message})`;
|
|
206
|
+
return `${loggerName}.${method}(${formattedMessage});`;
|
|
207
|
+
}
|
|
208
|
+
const formattedArgs = trimmedArgs.startsWith("'") ? trimmedArgs : `JSON.serialize(${trimmedArgs})`;
|
|
209
|
+
return `${loggerName}.debug(${formattedArgs});`;
|
|
130
210
|
}
|
|
131
211
|
static isComplexType(paramType) {
|
|
132
212
|
return (paramType.includes('<') ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument.js","sourceRoot":"","sources":["../../../../../src/commands/rflib/logging/apex/instrument.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAsCrC,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,+BAA+B,CAAC,CAAC;AAExF,MAAM,0BAA0B;IACvB,MAAM,CAAU,gBAAgB,GACrC,gGAAgG,CAAC;IAE3F,MAAM,CAAU,YAAY,GAClC,uJAAuJ,CAAC;IAClJ,MAAM,CAAU,WAAW,GAAG,mBAAmB,CAAC;IAClD,MAAM,CAAU,kBAAkB,GAAG,+DAA+D,CAAC;IACrG,MAAM,CAAU,kBAAkB,GAAG,UAAU,CAAC;IAChD,MAAM,CAAU,WAAW,GAAG,oCAAoC,CAAC;IACnE,MAAM,CAAU,kBAAkB,GACxC,0FAA0F,CAAC;IACrF,MAAM,CAAU,UAAU,GAAG,gFAAgF,CAAC;IAC9G,MAAM,CAAU,qBAAqB,GAAG,uCAAuC,CAAC;IAChF,MAAM,CAAU,kBAAkB,GAAG,iDAAiD,CAAC;IAEvF,MAAM,CAAU,eAAe,GAAG,IAAI,GAAG,CAAC;QAChD,QAAQ;QACR,SAAS;QACT,MAAM;QACN,SAAS;QACT,QAAQ;QACR,SAAS;QACT,MAAM;QACN,UAAU;QACV,MAAM;QACN,IAAI;KACL,CAAC,CAAC;IAEK,MAAM,CAAU,eAAe,GAAqB;QAC1D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,CAAC,sBAAsB,CAAC;QACjC,UAAU,EAAE,GAAG;QACf,QAAQ,EAAE,CAAC;QACX,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,IAAI;KAClB,CAAC;IAEK,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAe;QAC/C,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACzD,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAEM,MAAM,CAAC,cAAc,CAAC,OAAe;QAC1C,OAAO,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IAEM,MAAM,CAAC,YAAY,CAAC,OAAe;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACrD,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC;YAC7C,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ;SAC1C,CAAC;IACJ,CAAC;IAEM,MAAM,CAAC,oBAAoB,CAAC,OAAe,EAAE,SAAiB;QACnE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,UAAU,GAAG,qCAAqC,YAAY,kDAAkD,SAAS,KAAK,CAAC;YACrI,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,UAAU,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEM,MAAM,CAAC,yBAAyB,CAAC,OAAe,EAAE,UAAkB;QACzE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,KAAa,EAAE,GAAG,IAAe,EAAE,EAAE;YAC9E,MAAM,UAAU,GAAoB;gBAClC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAW;gBAC9B,MAAM,EAAE,IAAI,CAAC,CAAC,CAAW;gBACzB,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAW;gBAC3B,UAAU,EAAE,IAAI,CAAC,CAAC,CAAW;gBAC7B,UAAU,EAAE,IAAI,CAAC,CAAC,CAAW;gBAC7B,IAAI,EAAE,IAAI,CAAC,CAAC,CAAW;aACxB,CAAC;YAEF,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAEvE,OAAO,GAAG,KAAK,aAAa,UAAU,UAAU,UAAU,CAAC,UAAU,IAAI,SAAS;iBAC/E,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;iBACvB,IAAI,CAAC,IAAI,CAAC,KAAK,OAAO,MAAM,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,kBAAkB,CAAC,OAAe,EAAE,UAAkB;QAClE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAa,EAAE,YAAoB,EAAE,MAAc,EAAE,EAAE;YAC/F,MAAM,kBAAkB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YACxD,MAAM,aAAa,GAAG,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;YAC1E,MAAM,eAAe,GAAG,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAChE,MAAM,UAAU,GAAG,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAEpE,OAAO,GAAG,KAAK,iBAAiB,UAAU,gCAAgC,UAAU,QAAQ,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;QACtH,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,mBAAmB,CAAC,OAAe,EAAE,UAAkB;QACnE,MAAM,UAAU,GAAkB,EAAE,CAAC;QAErC,IAAI,QAAQ,GAAG,OAAO,CAAC,OAAO,CAC5B,IAAI,CAAC,kBAAkB,EACvB,CAAC,KAAa,EAAE,SAAiB,EAAE,SAAiB,EAAE,cAAsB,EAAE,MAAc,EAAE,EAAE;YAC9F,MAAM,kBAAkB,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACnE,UAAU,CAAC,IAAI,CAAC;gBACd,SAAS,EAAE,kBAAkB;gBAC7B,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAC;YAEH,MAAM,YAAY,GAAG,GAAG,UAAU,eAAe,kBAAkB,gBAAgB,CAAC;YAEpF,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO,OAAO,SAAS,gBAAgB,YAAY,GAAG,SAAS,KAAK,CAAC;YACvE,CAAC;iBAAM,IAAI,cAAc,EAAE,CAAC;gBAC1B,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC1D,OAAO,OAAO,SAAS,gBAAgB,YAAY,GAAG,SAAS,YAAY,CAAC;YAC9E,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CACF,CAAC;QAEF,QAAQ,GAAG,QAAQ,CAAC,OAAO,CACzB,IAAI,CAAC,UAAU,EACf,CAAC,KAAa,EAAE,SAAkB,EAAE,cAAuB,EAAE,MAAe,EAAE,EAAE;YAC9E,MAAM,SAAS,GAAG,UAAU;iBACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;iBACzC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAElF,MAAM,YAAY,GAAG,SAAS;gBAC5B,CAAC,CAAC,GAAG,UAAU,wBAAwB,SAAS,CAAC,SAAS,gBAAgB;gBAC1E,CAAC,CAAC,GAAG,UAAU,qCAAqC,CAAC;YAEvD,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO,oBAAoB,YAAY,GAAG,SAAS,GAAG,CAAC;YACzD,CAAC;iBAAM,IAAI,cAAc,EAAE,CAAC;gBAC1B,OAAO,oBAAoB,YAAY,GAAG,cAAc,SAAS,CAAC;YACpE,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CACF,CAAC;QAEF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEM,MAAM,CAAC,4BAA4B,CAAC,OAAe,EAAE,UAAkB;QAC5E,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,GAAG,UAAU,WAAW,YAAY,KAAK,CAAC,CAAC;IACtH,CAAC;IAEO,MAAM,CAAC,aAAa,CAAC,SAAiB;QAC5C,OAAO,CACL,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;YACvB,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;YACvB,SAAS,KAAK,QAAQ;YACtB,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CACnD,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,iBAAiB,CAAC,IAAY;QAC3C,MAAM,UAAU,GAAG,IAAI;YACrB,CAAC,CAAC,IAAI;iBACD,UAAU,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;iBACvC,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACjC,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,OAAO,GACX,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE;YAC3C,CAAC,CAAC,oBAAoB,UAAU;iBAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACT,MAAM,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC/D,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,kBAAkB,SAAS,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;YACpF,CAAC,CAAC;iBACD,IAAI,CAAC,IAAI,CAAC,IAAI;YACnB,CAAC,CAAC,EAAE,CAAC;QAET,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;IAC5C,CAAC;;AAGH,MAAM,CAAC,OAAO,OAAO,0BAA2B,SAAQ,SAA2C;IAC1F,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,MAAM,CAAU,KAAK,GAAG;QAC7B,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC;YACvB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YACxD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,8BAA8B,CAAC;YAChE,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC;YACpB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,sBAAsB,CAAC;YACpD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YAC5D,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,KAAK;SACf,CAAC;QACF,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;YACtB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,wBAAwB,CAAC;YACtD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,4BAA4B,CAAC;YAC9D,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,KAAK;SACf,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;YACrB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC;YACnD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,yBAAyB,CAAC;YAC3D,OAAO,EAAE,KAAK;SACf,CAAC;QACF,mBAAmB,EAAE,KAAK,CAAC,OAAO,CAAC;YACjC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,iCAAiC,CAAC;YAC/D,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,qCAAqC,CAAC;YACvE,OAAO,EAAE,KAAK;SACf,CAAC;KACH,CAAC;IAEM,MAAM,CAAU;IACP,KAAK,GAAqC;QACzD,cAAc,EAAE,CAAC;QACjB,aAAa,EAAE,CAAC;QAChB,cAAc,EAAE,CAAC;KAClB,CAAC;IAEK,KAAK,CAAC,GAAG;QACd,IAAI,CAAC,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;QAE9B,MAAM,mBAAmB,GAA2B;YAClD,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;YACpB,gBAAgB,EAAE,KAAK,CAAC,mBAAmB,CAAC;SAC7C,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,4BAA4B,UAAU,sBAAsB,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;QAE/C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACjC,MAAM,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC;QACvE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,QAAQ,IAAI,CAAC,CAAC;QAEhE,IAAI,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;QAE1D,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC5B,OAAe,EACf,QAAiB,EACjB,mBAA2C;QAE3C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5E,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAEhD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC;gBACrE,OAAO;YACT,CAAC;YAED,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/D,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC;gBACpE,OAAO;YACT,CAAC;YAED,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAChC,MAAM,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,eAAe,CAC3B,QAAgB,EAChB,QAAiB,EACjB,mBAA2C;QAE3C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;QACvD,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC3D,MAAM,eAAe,GAAG,OAAO,CAAC;QAEhC,IAAI,mBAAmB,CAAC,gBAAgB,IAAI,0BAA0B,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/F,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qCAAqC,QAAQ,EAAE,CAAC,CAAC;YAClE,OAAO;QACT,CAAC;QAED,OAAO,GAAG,OAAO,CAAC,OAAO,CACvB,0BAA0B,CAAC,gBAAgB,EAC3C,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,uDAAuD,CAC3E,CAAC;QAEF,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;YAC3B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,IAAI,CAAC;oBACH,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ;wBAC/C,CAAC,CAAC,MAAM,0BAA0B,CAAC,aAAa,CAAC,OAAO,CAAC;wBACzD,CAAC,CAAC,OAAO,CAAC;oBAEZ,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;oBAEpD,IAAI,mBAAmB,CAAC,QAAQ,EAAE,CAAC;wBACjC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;wBAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qCAAqC,QAAQ,EAAE,CAAC,CAAC;oBACpE,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC;oBACtD,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,QAAQ,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAC5G,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;oBAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0CAA0C,QAAQ,EAAE,CAAC,CAAC;gBACzE,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAC/B,QAAgB,EAChB,QAAiB,EACjB,mBAA2C;QAE3C,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC;QAEpD,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAC5B,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC3D,MAAM,eAAe,GAAG,OAAO,CAAC;YAEhC,IAAI,mBAAmB,CAAC,gBAAgB,IAAI,0BAA0B,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/F,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,SAAS,EAAE,CAAC,CAAC;gBAC9D,OAAO;YACT,CAAC;YAED,MAAM,EAAE,YAAY,EAAE,GAAG,0BAA0B,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAC1E,OAAO,GAAG,0BAA0B,CAAC,oBAAoB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAC9E,OAAO,GAAG,0BAA0B,CAAC,yBAAyB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACtF,OAAO,GAAG,0BAA0B,CAAC,4BAA4B,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACzF,OAAO,GAAG,0BAA0B,CAAC,kBAAkB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YAE/E,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC;gBAC9B,OAAO,GAAG,0BAA0B,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YAClF,CAAC;YAED,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;gBAChC,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;gBAC3B,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,IAAI,CAAC;wBACH,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ;4BAC/C,CAAC,CAAC,MAAM,0BAA0B,CAAC,aAAa,CAAC,OAAO,CAAC;4BACzD,CAAC,CAAC,OAAO,CAAC;wBAEZ,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;wBAEpD,IAAI,mBAAmB,CAAC,QAAQ,EAAE,CAAC;4BACjC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;4BAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;wBAC1D,CAAC;6BAAM,CAAC;4BACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,QAAQ,EAAE,CAAC,CAAC;wBAC5C,CAAC;oBACH,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,QAAQ,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;wBAC5G,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;wBAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,QAAQ,EAAE,CAAC,CAAC;oBAC/D,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,SAAS,EAAE,EAAE,KAAK,CAAC,CAAC;YAChE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC","sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { SfCommand, Flags } from '@salesforce/sf-plugins-core';\nimport { Messages, Logger } from '@salesforce/core';\nimport * as prettier from 'prettier';\n\ntype ApexMethodMatch = {\n auraEnabled?: string;\n access: string;\n isStatic?: string;\n returnType: string;\n methodName: string;\n args: string;\n}\n\ntype IfCondition = {\n condition: string;\n position: number;\n}\n\ntype InstrumentationOptions = {\n readonly prettier: boolean;\n readonly noIf: boolean;\n readonly skipInstrumented: boolean;\n}\n\ntype LoggerInfo = {\n readonly exists: boolean;\n readonly variableName: string;\n}\n\ntype ProcessedParameters = {\n readonly paramList: readonly string[];\n readonly logArgs: string;\n}\n\nexport type RflibLoggingApexInstrumentResult = {\n processedFiles: number;\n modifiedFiles: number;\n formattedFiles: number;\n}\n\nMessages.importMessagesDirectoryFromMetaUrl(import.meta.url);\nconst messages = Messages.loadMessages('rflib-plugin', 'rflib.logging.apex.instrument');\n\nclass ApexInstrumentationService {\n public static readonly TEST_SETUP_REGEX =\n /@TestSetup\\s+((public|private|protected|global)s+)?(?:static\\s+)?void\\s+(\\w+)\\s*\\([^)]*\\)\\s*{/g;\n\n private static readonly METHOD_REGEX =\n /(@AuraEnabled\\s*[\\s\\S]*?)?\\b(public|private|protected|global)\\s+(static\\s+)?(?:(\\w+(?:\\s*<(?:[^<>]|<[^<>]*>)*>)?)|void)\\s+(\\w+)\\s*\\(([\\s\\S]*?)\\)\\s*{/g;\n private static readonly CLASS_REGEX = /\\bclass\\s+\\w+\\s*{/;\n private static readonly CLASS_LOGGER_REGEX = /\\bprivate\\s+(?:static\\s+)?(?:final\\s+)?rflib_Logger\\s+(\\w+)\\b/;\n private static readonly GENERIC_ARGS_REGEX = /<[^>]+>/g;\n private static readonly CATCH_REGEX = /catch\\s*\\(\\s*\\w+\\s+(\\w+)\\s*\\)\\s*{/g;\n private static readonly IF_STATEMENT_REGEX =\n /if\\s*\\((.*?)\\)\\s*(?:{([^]*?(?:(?<!{){(?:[^]*?)}(?!})[^]*?)*)}|([^{].*?)(?=\\s*(?:;|$));)/g;\n private static readonly ELSE_REGEX = /\\s*else(?!\\s*if\\b)\\s*(?:{((?:[^{}]|{(?:[^{}]|{[^{}]*})*})*)}|([^{;]*(?:;|$)))/g;\n private static readonly IS_INSTRUMENTED_REGEX = /(\\brflib_Logger\\b|\\brflib_TestUtil\\b)/;\n private static readonly SYSTEM_DEBUG_REGEX = /System\\.debug\\s*\\(\\s*['\"]([^'\"]*)['\"]\\s*\\)\\s*;/g;\n\n private static readonly PRIMITIVE_TYPES = new Set([\n 'STRING',\n 'INTEGER',\n 'LONG',\n 'DECIMAL',\n 'DOUBLE',\n 'BOOLEAN',\n 'DATE',\n 'DATETIME',\n 'TIME',\n 'ID',\n ]);\n\n private static readonly PRETTIER_CONFIG: prettier.Options = {\n parser: 'apex',\n plugins: ['prettier-plugin-apex'],\n printWidth: 120,\n tabWidth: 4,\n useTabs: false,\n singleQuote: true,\n };\n\n public static async formatContent(content: string): Promise<string> {\n try {\n return await prettier.format(content, this.PRETTIER_CONFIG);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Formatting failed: ${error.message}`);\n }\n throw new Error('Formatting failed with unknown error');\n }\n }\n\n public static isInstrumented(content: string): boolean {\n return this.IS_INSTRUMENTED_REGEX.test(content);\n }\n\n public static detectLogger(content: string): LoggerInfo {\n const match = content.match(this.CLASS_LOGGER_REGEX);\n return {\n exists: this.CLASS_LOGGER_REGEX.test(content),\n variableName: match ? match[1] : 'LOGGER',\n };\n }\n\n public static addLoggerDeclaration(content: string, className: string): string {\n const { exists, variableName } = this.detectLogger(content);\n if (!exists) {\n const loggerDecl = `private static final rflib_Logger ${variableName} = rflib_LoggerUtil.getFactory().createLogger('${className}');`;\n return content.replace(this.CLASS_REGEX, `$&\\n ${loggerDecl}`);\n }\n return content;\n }\n\n public static processMethodDeclarations(content: string, loggerName: string): string {\n return content.replace(this.METHOD_REGEX, (match: string, ...args: unknown[]) => {\n const methodInfo: ApexMethodMatch = {\n auraEnabled: args[0] as string,\n access: args[1] as string,\n isStatic: args[2] as string,\n returnType: args[3] as string,\n methodName: args[4] as string,\n args: args[5] as string,\n };\n\n const { paramList, logArgs } = this.processParameters(methodInfo.args);\n\n return `${match}\\n ${loggerName}.info('${methodInfo.methodName}(${paramList\n .map((_, i) => `{${i}}`)\n .join(', ')})'${logArgs});\\n`;\n });\n }\n\n public static processCatchBlocks(content: string, loggerName: string): string {\n return content.replace(this.CATCH_REGEX, (match: string, exceptionVar: string, offset: number) => {\n const contentBeforeCatch = content.substring(0, offset);\n const methodMatches = [...contentBeforeCatch.matchAll(this.METHOD_REGEX)];\n const lastMethodMatch = methodMatches[methodMatches.length - 1];\n const methodName = lastMethodMatch ? lastMethodMatch[5] : 'unknown';\n\n return `${match}\\n ${loggerName}.error('An error occurred in ${methodName}()', ${exceptionVar.trim()});`;\n });\n }\n\n public static processIfStatements(content: string, loggerName: string): string {\n const conditions: IfCondition[] = [];\n\n let modified = content.replace(\n this.IF_STATEMENT_REGEX,\n (match: string, condition: string, blockBody: string, singleLineBody: string, offset: number) => {\n const cleanedUpCondition = condition.trim().replaceAll(\"'\", \"\\\\'\");\n conditions.push({\n condition: cleanedUpCondition,\n position: offset,\n });\n\n const logStatement = `${loggerName}.debug('if (${cleanedUpCondition})');\\n `;\n\n if (blockBody) {\n return `if (${condition}) {\\n ${logStatement}${blockBody}}\\n`;\n } else if (singleLineBody) {\n const cleanBody = singleLineBody.replace(/;$/, '').trim();\n return `if (${condition}) {\\n ${logStatement}${cleanBody};\\n }\\n`;\n }\n return match;\n },\n );\n\n modified = modified.replace(\n this.ELSE_REGEX,\n (match: string, blockBody?: string, singleLineBody?: string, offset?: number) => {\n const nearestIf = conditions\n .filter((c) => c.position < (offset ?? 0))\n .reduce((prev, curr) => (!prev || curr.position > prev.position ? curr : prev));\n\n const logStatement = nearestIf\n ? `${loggerName}.debug('else for if (${nearestIf.condition})');\\n `\n : `${loggerName}.debug('else statement');\\n `;\n\n if (blockBody) {\n return ` else {\\n ${logStatement}${blockBody}}`;\n } else if (singleLineBody) {\n return ` else {\\n ${logStatement}${singleLineBody}\\n }`;\n }\n return match;\n },\n );\n\n return modified;\n }\n\n public static processSystemDebugStatements(content: string, loggerName: string): string {\n return content.replace(this.SYSTEM_DEBUG_REGEX, (match, debugMessage) => `${loggerName}.debug('${debugMessage}');`);\n }\n\n private static isComplexType(paramType: string): boolean {\n return (\n paramType.includes('<') ||\n paramType.includes('[') ||\n paramType === 'Object' ||\n !this.PRIMITIVE_TYPES.has(paramType.toUpperCase())\n );\n }\n\n private static processParameters(args: string): ProcessedParameters {\n const parameters = args\n ? args\n .replaceAll(this.GENERIC_ARGS_REGEX, '')\n .split(',')\n .map((param) => param.trim())\n : [];\n\n const logArgs =\n parameters.length > 0 && parameters[0] !== ''\n ? `, new Object[] { ${parameters\n .map((p) => {\n const [paramType, ...rest] = p.split(' ');\n const paramName = rest.length > 0 ? rest.join(' ') : paramType;\n return this.isComplexType(paramType) ? `JSON.serialize(${paramName})` : paramName;\n })\n .join(', ')} }`\n : '';\n\n return { paramList: parameters, logArgs };\n }\n}\n\nexport default class RflibLoggingApexInstrument extends SfCommand<RflibLoggingApexInstrumentResult> {\n public static readonly summary = messages.getMessage('summary');\n public static readonly description = messages.getMessage('description');\n public static readonly examples = messages.getMessages('examples');\n\n public static readonly flags = {\n sourcepath: Flags.string({\n summary: messages.getMessage('flags.sourcepath.summary'),\n description: messages.getMessage('flags.sourcepath.description'),\n char: 's',\n required: true,\n }),\n dryrun: Flags.boolean({\n summary: messages.getMessage('flags.dryrun.summary'),\n description: messages.getMessage('flags.dryrun.description'),\n char: 'd',\n default: false,\n }),\n prettier: Flags.boolean({\n summary: messages.getMessage('flags.prettier.summary'),\n description: messages.getMessage('flags.prettier.description'),\n char: 'p',\n default: false,\n }),\n 'no-if': Flags.boolean({\n summary: messages.getMessage('flags.no-if.summary'),\n description: messages.getMessage('flags.no-if.description'),\n default: false,\n }),\n 'skip-instrumented': Flags.boolean({\n summary: messages.getMessage('flags.skip-instrumented.summary'),\n description: messages.getMessage('flags.skip-instrumented.description'),\n default: false,\n }),\n };\n\n private logger!: Logger;\n private readonly stats: RflibLoggingApexInstrumentResult = {\n processedFiles: 0,\n modifiedFiles: 0,\n formattedFiles: 0,\n };\n\n public async run(): Promise<RflibLoggingApexInstrumentResult> {\n this.logger = await Logger.child(this.ctor.name);\n const startTime = Date.now();\n\n const { flags } = await this.parse(RflibLoggingApexInstrument);\n const sourcePath = flags.sourcepath;\n const isDryRun = flags.dryrun;\n\n const instrumentationOpts: InstrumentationOptions = {\n prettier: flags.prettier,\n noIf: flags['no-if'],\n skipInstrumented: flags['skip-instrumented'],\n };\n\n this.log(`Scanning Apex classes in ${sourcePath} and sub directories`);\n this.logger.debug(`Dry run mode: ${isDryRun}`);\n\n this.spinner.start('Running...');\n await this.processDirectory(sourcePath, isDryRun, instrumentationOpts);\n this.spinner.stop();\n\n const duration = Date.now() - startTime;\n this.logger.debug(`Completed instrumentation in ${duration}ms`);\n\n this.log('\\nInstrumentation complete.');\n this.log(`Processed files: ${this.stats.processedFiles}`);\n this.log(`Modified files: ${this.stats.modifiedFiles}`);\n this.log(`Formatted files: ${this.stats.formattedFiles}`);\n\n return { ...this.stats };\n }\n\n private async processDirectory(\n dirPath: string,\n isDryRun: boolean,\n instrumentationOpts: InstrumentationOptions,\n ): Promise<void> {\n this.logger.debug(`Processing directory: ${dirPath}`);\n const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });\n\n await Promise.all(\n entries.map(async (entry) => {\n const filePath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n await this.processDirectory(filePath, isDryRun, instrumentationOpts);\n return;\n }\n\n if (entry.name.includes('Test') && entry.name.endsWith('.cls')) {\n await this.processTestFile(filePath, isDryRun, instrumentationOpts);\n return;\n }\n\n if (entry.name.endsWith('.cls')) {\n await this.instrumentApexClass(filePath, isDryRun, instrumentationOpts);\n }\n }),\n );\n }\n\n private async processTestFile(\n filePath: string,\n isDryRun: boolean,\n instrumentationOpts: InstrumentationOptions,\n ): Promise<void> {\n this.logger.debug(`Processing test file: ${filePath}`);\n let content = await fs.promises.readFile(filePath, 'utf8');\n const originalContent = content;\n\n if (instrumentationOpts.skipInstrumented && ApexInstrumentationService.isInstrumented(content)) {\n this.logger.info(`Skipping instrumented test class: ${filePath}`);\n return;\n }\n\n content = content.replace(\n ApexInstrumentationService.TEST_SETUP_REGEX,\n (match) => `${match}\\n rflib_TestUtil.prepareLoggerForUnitTests();`,\n );\n\n if (content !== originalContent) {\n this.stats.modifiedFiles++;\n if (!isDryRun) {\n try {\n const finalContent = instrumentationOpts.prettier\n ? await ApexInstrumentationService.formatContent(content)\n : content;\n\n await fs.promises.writeFile(filePath, finalContent);\n\n if (instrumentationOpts.prettier) {\n this.stats.formattedFiles++;\n this.logger.info(`Modified and formatted test file: ${filePath}`);\n } else {\n this.logger.info(`Modified test file: ${filePath}`);\n }\n } catch (error) {\n this.logger.warn(`Failed to format ${filePath}: ${error instanceof Error ? error.message : String(error)}`);\n await fs.promises.writeFile(filePath, content);\n this.logger.info(`Modified test file without formatting: ${filePath}`);\n }\n } else {\n this.logger.info(`Would modify test file: ${filePath}`);\n }\n }\n }\n\n private async instrumentApexClass(\n filePath: string,\n isDryRun: boolean,\n instrumentationOpts: InstrumentationOptions,\n ): Promise<void> {\n const className = path.basename(filePath, '.cls');\n this.logger.debug(`Processing class: ${className}`);\n\n try {\n this.stats.processedFiles++;\n let content = await fs.promises.readFile(filePath, 'utf8');\n const originalContent = content;\n\n if (instrumentationOpts.skipInstrumented && ApexInstrumentationService.isInstrumented(content)) {\n this.logger.info(`Skipping instrumented class: ${className}`);\n return;\n }\n\n const { variableName } = ApexInstrumentationService.detectLogger(content);\n content = ApexInstrumentationService.addLoggerDeclaration(content, className);\n content = ApexInstrumentationService.processMethodDeclarations(content, variableName);\n content = ApexInstrumentationService.processSystemDebugStatements(content, variableName);\n content = ApexInstrumentationService.processCatchBlocks(content, variableName);\n\n if (!instrumentationOpts.noIf) {\n content = ApexInstrumentationService.processIfStatements(content, variableName);\n }\n\n if (content !== originalContent) {\n this.stats.modifiedFiles++;\n if (!isDryRun) {\n try {\n const finalContent = instrumentationOpts.prettier\n ? await ApexInstrumentationService.formatContent(content)\n : content;\n\n await fs.promises.writeFile(filePath, finalContent);\n\n if (instrumentationOpts.prettier) {\n this.stats.formattedFiles++;\n this.logger.info(`Modified and formatted: ${filePath}`);\n } else {\n this.logger.info(`Modified: ${filePath}`);\n }\n } catch (error) {\n this.logger.warn(`Failed to format ${filePath}: ${error instanceof Error ? error.message : String(error)}`);\n await fs.promises.writeFile(filePath, content);\n this.logger.info(`Modified without formatting: ${filePath}`);\n }\n } else {\n this.logger.info(`Would modify: ${filePath}`);\n }\n }\n } catch (error) {\n this.logger.error(`Error processing class ${className}`, error);\n throw error;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"instrument.js","sourceRoot":"","sources":["../../../../../src/commands/rflib/logging/apex/instrument.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { SfCommand, Flags } from '@salesforce/sf-plugins-core';\nimport { Messages, Logger } from '@salesforce/core';\nimport * as prettier from 'prettier';\n\ntype ApexMethodMatch = {\n auraEnabled?: string;\n access: string;\n isStatic?: string;\n returnType: string;\n methodName: string;\n args: string;\n}\n\ntype IfCondition = {\n condition: string;\n position: number;\n}\n\ntype InstrumentationOptions = {\n readonly prettier: boolean;\n readonly noIf: boolean;\n readonly skipInstrumented: boolean;\n}\n\ntype LoggerInfo = {\n readonly exists: boolean;\n readonly variableName: string;\n}\n\ntype ProcessedParameters = {\n readonly paramList: readonly string[];\n readonly logArgs: string;\n}\n\nexport type RflibLoggingApexInstrumentResult = {\n processedFiles: number;\n modifiedFiles: number;\n formattedFiles: number;\n}\n\nMessages.importMessagesDirectoryFromMetaUrl(import.meta.url);\nconst messages = Messages.loadMessages('rflib-plugin', 'rflib.logging.apex.instrument');\n\nclass ApexInstrumentationService {\n public static readonly TEST_SETUP_REGEX =\n /@TestSetup\\s+((public|private|protected|global)s+)?(?:static\\s+)?void\\s+(\\w+)\\s*\\([^)]*\\)\\s*{/g;\n\n private static readonly METHOD_REGEX =\n /(@AuraEnabled\\s*[\\s\\S]*?)?\\b(public|private|protected|global)\\s+(static\\s+)?(?:(\\w+(?:\\s*<(?:[^<>]|<[^<>]*>)*>)?)|void)\\s+(\\w+)\\s*\\(([\\s\\S]*?)\\)\\s*{/g;\n private static readonly CLASS_REGEX = /\\bclass\\s+\\w+\\s*{/;\n private static readonly CLASS_LOGGER_REGEX = /\\bprivate\\s+(?:static\\s+)?(?:final\\s+)?rflib_Logger\\s+(\\w+)\\b/;\n private static readonly GENERIC_ARGS_REGEX = /<[^>]+>/g;\n private static readonly CATCH_REGEX = /catch\\s*\\(\\s*\\w+\\s+(\\w+)\\s*\\)\\s*{/g;\n private static readonly IF_STATEMENT_REGEX =\n /if\\s*\\((.*?)\\)\\s*(?:{([^]*?(?:(?<!{){(?:[^]*?)}(?!})[^]*?)*)}|([^{].*?)(?=\\s*(?:;|$));)/g;\n private static readonly ELSE_REGEX = /\\s*else(?!\\s*if\\b)\\s*(?:{((?:[^{}]|{(?:[^{}]|{[^{}]*})*})*)}|([^{;]*(?:;|$)))/g;\n private static readonly IS_INSTRUMENTED_REGEX = /(\\brflib_Logger\\b|\\brflib_TestUtil\\b)/;\n private static readonly SYSTEM_DEBUG_START_REGEX = /System\\.debug\\s*\\(/g;\n private static readonly LOGGING_LEVEL_REGEX = /^LoggingLevel\\.(\\w+)\\s*,\\s*([\\s\\S]*)$/;\n\n private static readonly PRIMITIVE_TYPES = new Set([\n 'STRING',\n 'INTEGER',\n 'LONG',\n 'DECIMAL',\n 'DOUBLE',\n 'BOOLEAN',\n 'DATE',\n 'DATETIME',\n 'TIME',\n 'ID',\n ]);\n\n private static readonly PRETTIER_CONFIG: prettier.Options = {\n parser: 'apex',\n plugins: ['prettier-plugin-apex'],\n printWidth: 120,\n tabWidth: 4,\n useTabs: false,\n singleQuote: true,\n };\n\n public static async formatContent(content: string): Promise<string> {\n try {\n return await prettier.format(content, this.PRETTIER_CONFIG);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Formatting failed: ${error.message}`);\n }\n throw new Error('Formatting failed with unknown error');\n }\n }\n\n public static isInstrumented(content: string): boolean {\n return this.IS_INSTRUMENTED_REGEX.test(content);\n }\n\n public static detectLogger(content: string): LoggerInfo {\n const match = content.match(this.CLASS_LOGGER_REGEX);\n return {\n exists: this.CLASS_LOGGER_REGEX.test(content),\n variableName: match ? match[1] : 'LOGGER',\n };\n }\n\n public static addLoggerDeclaration(content: string, className: string): string {\n const { exists, variableName } = this.detectLogger(content);\n if (!exists) {\n const loggerDecl = `private static final rflib_Logger ${variableName} = rflib_LoggerUtil.getFactory().createLogger('${className}');`;\n return content.replace(this.CLASS_REGEX, `$&\\n ${loggerDecl}`);\n }\n return content;\n }\n\n public static processMethodDeclarations(content: string, loggerName: string): string {\n return content.replace(this.METHOD_REGEX, (match: string, ...args: unknown[]) => {\n const methodInfo: ApexMethodMatch = {\n auraEnabled: args[0] as string,\n access: args[1] as string,\n isStatic: args[2] as string,\n returnType: args[3] as string,\n methodName: args[4] as string,\n args: args[5] as string,\n };\n\n const { paramList, logArgs } = this.processParameters(methodInfo.args);\n\n return `${match}\\n ${loggerName}.info('${methodInfo.methodName}(${paramList\n .map((_, i) => `{${i}}`)\n .join(', ')})'${logArgs});\\n`;\n });\n }\n\n public static processCatchBlocks(content: string, loggerName: string): string {\n return content.replace(this.CATCH_REGEX, (match: string, exceptionVar: string, offset: number) => {\n const contentBeforeCatch = content.substring(0, offset);\n const methodMatches = [...contentBeforeCatch.matchAll(this.METHOD_REGEX)];\n const lastMethodMatch = methodMatches[methodMatches.length - 1];\n const methodName = lastMethodMatch ? lastMethodMatch[5] : 'unknown';\n\n return `${match}\\n ${loggerName}.error('An error occurred in ${methodName}()', ${exceptionVar.trim()});`;\n });\n }\n\n public static processIfStatements(content: string, loggerName: string): string {\n const conditions: IfCondition[] = [];\n\n let modified = content.replace(\n this.IF_STATEMENT_REGEX,\n (match: string, condition: string, blockBody: string, singleLineBody: string, offset: number) => {\n const cleanedUpCondition = condition.trim().replaceAll(\"'\", \"\\\\'\");\n conditions.push({\n condition: cleanedUpCondition,\n position: offset,\n });\n\n const logStatement = `${loggerName}.debug('if (${cleanedUpCondition})');\\n `;\n\n if (blockBody) {\n return `if (${condition}) {\\n ${logStatement}${blockBody}}\\n`;\n } else if (singleLineBody) {\n const cleanBody = singleLineBody.replace(/;$/, '').trim();\n return `if (${condition}) {\\n ${logStatement}${cleanBody};\\n }\\n`;\n }\n return match;\n },\n );\n\n modified = modified.replace(\n this.ELSE_REGEX,\n (match: string, blockBody?: string, singleLineBody?: string, offset?: number) => {\n const nearestIf = conditions\n .filter((c) => c.position < (offset ?? 0))\n .reduce((prev, curr) => (!prev || curr.position > prev.position ? curr : prev));\n\n const logStatement = nearestIf\n ? `${loggerName}.debug('else for if (${nearestIf.condition})');\\n `\n : `${loggerName}.debug('else statement');\\n `;\n\n if (blockBody) {\n return ` else {\\n ${logStatement}${blockBody}}`;\n } else if (singleLineBody) {\n return ` else {\\n ${logStatement}${singleLineBody}\\n }`;\n }\n return match;\n },\n );\n\n return modified;\n }\n\n public static processSystemDebugStatements(content: string, loggerName: string): string {\n const debugStartRegex = new RegExp(this.SYSTEM_DEBUG_START_REGEX);\n let match;\n let lastIndex = 0;\n let output = '';\n\n while ((match = debugStartRegex.exec(content)) !== null) {\n output += content.substring(lastIndex, match.index);\n\n const openParenIndex = match.index + match[0].length - 1;\n let depth = 1;\n let i = openParenIndex + 1;\n let inString = false;\n let isEscaped = false;\n\n for (; i < content.length && depth > 0; i++) {\n const char = content[i];\n\n if (inString) {\n if (isEscaped) {\n isEscaped = false;\n } else if (char === '\\\\') {\n isEscaped = true;\n } else if (char === \"'\") {\n inString = false;\n }\n } else if (char === \"'\") {\n inString = true;\n } else if (char === '(') {\n depth++;\n } else if (char === ')') {\n depth--;\n }\n }\n\n if (depth === 0) {\n const closeParenIndex = i - 1;\n const remaining = content.substring(closeParenIndex + 1);\n const semiColonMatch = remaining.match(/^\\s*;/);\n\n if (semiColonMatch) {\n const endOfStatement = closeParenIndex + 1 + semiColonMatch[0].length;\n const args = content.substring(openParenIndex + 1, closeParenIndex);\n const processed = this.transformSystemDebug(args, loggerName);\n output += processed;\n lastIndex = endOfStatement;\n debugStartRegex.lastIndex = endOfStatement;\n } else {\n output += match[0];\n lastIndex = match.index + match[0].length;\n }\n } else {\n output += match[0];\n lastIndex = match.index + match[0].length;\n }\n }\n\n output += content.substring(lastIndex);\n return output;\n }\n\n private static transformSystemDebug(args: string, loggerName: string): string {\n const trimmedArgs = args.trim();\n const levelMatch = trimmedArgs.match(this.LOGGING_LEVEL_REGEX);\n\n if (levelMatch) {\n const level = levelMatch[1].toUpperCase();\n const message = levelMatch[2].trim();\n let method = 'debug';\n\n if (level === 'ERROR') {\n method = 'error';\n } else if (level === 'WARN') {\n method = 'warn';\n } else if (level === 'INFO') {\n method = 'info';\n }\n\n const formattedMessage = message.startsWith(\"'\") ? message : `JSON.serialize(${message})`;\n return `${loggerName}.${method}(${formattedMessage});`;\n }\n\n const formattedArgs = trimmedArgs.startsWith(\"'\") ? trimmedArgs : `JSON.serialize(${trimmedArgs})`;\n return `${loggerName}.debug(${formattedArgs});`;\n }\n\n private static isComplexType(paramType: string): boolean {\n return (\n paramType.includes('<') ||\n paramType.includes('[') ||\n paramType === 'Object' ||\n !this.PRIMITIVE_TYPES.has(paramType.toUpperCase())\n );\n }\n\n private static processParameters(args: string): ProcessedParameters {\n const parameters = args\n ? args\n .replaceAll(this.GENERIC_ARGS_REGEX, '')\n .split(',')\n .map((param) => param.trim())\n : [];\n\n const logArgs =\n parameters.length > 0 && parameters[0] !== ''\n ? `, new Object[] { ${parameters\n .map((p) => {\n const [paramType, ...rest] = p.split(' ');\n const paramName = rest.length > 0 ? rest.join(' ') : paramType;\n return this.isComplexType(paramType) ? `JSON.serialize(${paramName})` : paramName;\n })\n .join(', ')} }`\n : '';\n\n return { paramList: parameters, logArgs };\n }\n}\n\nexport default class RflibLoggingApexInstrument extends SfCommand<RflibLoggingApexInstrumentResult> {\n public static readonly summary = messages.getMessage('summary');\n public static readonly description = messages.getMessage('description');\n public static readonly examples = messages.getMessages('examples');\n\n public static readonly flags = {\n sourcepath: Flags.string({\n summary: messages.getMessage('flags.sourcepath.summary'),\n description: messages.getMessage('flags.sourcepath.description'),\n char: 's',\n required: true,\n }),\n dryrun: Flags.boolean({\n summary: messages.getMessage('flags.dryrun.summary'),\n description: messages.getMessage('flags.dryrun.description'),\n char: 'd',\n default: false,\n }),\n prettier: Flags.boolean({\n summary: messages.getMessage('flags.prettier.summary'),\n description: messages.getMessage('flags.prettier.description'),\n char: 'p',\n default: false,\n }),\n 'no-if': Flags.boolean({\n summary: messages.getMessage('flags.no-if.summary'),\n description: messages.getMessage('flags.no-if.description'),\n default: false,\n }),\n 'skip-instrumented': Flags.boolean({\n summary: messages.getMessage('flags.skip-instrumented.summary'),\n description: messages.getMessage('flags.skip-instrumented.description'),\n default: false,\n }),\n };\n\n private logger!: Logger;\n private readonly stats: RflibLoggingApexInstrumentResult = {\n processedFiles: 0,\n modifiedFiles: 0,\n formattedFiles: 0,\n };\n\n public async run(): Promise<RflibLoggingApexInstrumentResult> {\n this.logger = await Logger.child(this.ctor.name);\n const startTime = Date.now();\n\n const { flags } = await this.parse(RflibLoggingApexInstrument);\n const sourcePath = flags.sourcepath;\n const isDryRun = flags.dryrun;\n\n const instrumentationOpts: InstrumentationOptions = {\n prettier: flags.prettier,\n noIf: flags['no-if'],\n skipInstrumented: flags['skip-instrumented'],\n };\n\n this.log(`Scanning Apex classes in ${sourcePath} and sub directories`);\n this.logger.debug(`Dry run mode: ${isDryRun}`);\n\n this.spinner.start('Running...');\n await this.processDirectory(sourcePath, isDryRun, instrumentationOpts);\n this.spinner.stop();\n\n const duration = Date.now() - startTime;\n this.logger.debug(`Completed instrumentation in ${duration}ms`);\n\n this.log('\\nInstrumentation complete.');\n this.log(`Processed files: ${this.stats.processedFiles}`);\n this.log(`Modified files: ${this.stats.modifiedFiles}`);\n this.log(`Formatted files: ${this.stats.formattedFiles}`);\n\n return { ...this.stats };\n }\n\n private async processDirectory(\n dirPath: string,\n isDryRun: boolean,\n instrumentationOpts: InstrumentationOptions,\n ): Promise<void> {\n this.logger.debug(`Processing directory: ${dirPath}`);\n const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });\n\n await Promise.all(\n entries.map(async (entry) => {\n const filePath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n await this.processDirectory(filePath, isDryRun, instrumentationOpts);\n return;\n }\n\n if (entry.name.includes('Test') && entry.name.endsWith('.cls')) {\n await this.processTestFile(filePath, isDryRun, instrumentationOpts);\n return;\n }\n\n if (entry.name.endsWith('.cls')) {\n await this.instrumentApexClass(filePath, isDryRun, instrumentationOpts);\n }\n }),\n );\n }\n\n private async processTestFile(\n filePath: string,\n isDryRun: boolean,\n instrumentationOpts: InstrumentationOptions,\n ): Promise<void> {\n this.logger.debug(`Processing test file: ${filePath}`);\n let content = await fs.promises.readFile(filePath, 'utf8');\n const originalContent = content;\n\n if (instrumentationOpts.skipInstrumented && ApexInstrumentationService.isInstrumented(content)) {\n this.logger.info(`Skipping instrumented test class: ${filePath}`);\n return;\n }\n\n content = content.replace(\n ApexInstrumentationService.TEST_SETUP_REGEX,\n (match) => `${match}\\n rflib_TestUtil.prepareLoggerForUnitTests();`,\n );\n\n if (content !== originalContent) {\n this.stats.modifiedFiles++;\n if (!isDryRun) {\n try {\n const finalContent = instrumentationOpts.prettier\n ? await ApexInstrumentationService.formatContent(content)\n : content;\n\n await fs.promises.writeFile(filePath, finalContent);\n\n if (instrumentationOpts.prettier) {\n this.stats.formattedFiles++;\n this.logger.info(`Modified and formatted test file: ${filePath}`);\n } else {\n this.logger.info(`Modified test file: ${filePath}`);\n }\n } catch (error) {\n this.logger.warn(`Failed to format ${filePath}: ${error instanceof Error ? error.message : String(error)}`);\n await fs.promises.writeFile(filePath, content);\n this.logger.info(`Modified test file without formatting: ${filePath}`);\n }\n } else {\n this.logger.info(`Would modify test file: ${filePath}`);\n }\n }\n }\n\n private async instrumentApexClass(\n filePath: string,\n isDryRun: boolean,\n instrumentationOpts: InstrumentationOptions,\n ): Promise<void> {\n const className = path.basename(filePath, '.cls');\n this.logger.debug(`Processing class: ${className}`);\n\n try {\n this.stats.processedFiles++;\n let content = await fs.promises.readFile(filePath, 'utf8');\n const originalContent = content;\n\n if (instrumentationOpts.skipInstrumented && ApexInstrumentationService.isInstrumented(content)) {\n this.logger.info(`Skipping instrumented class: ${className}`);\n return;\n }\n\n const { variableName } = ApexInstrumentationService.detectLogger(content);\n content = ApexInstrumentationService.addLoggerDeclaration(content, className);\n content = ApexInstrumentationService.processMethodDeclarations(content, variableName);\n content = ApexInstrumentationService.processSystemDebugStatements(content, variableName);\n content = ApexInstrumentationService.processCatchBlocks(content, variableName);\n\n if (!instrumentationOpts.noIf) {\n content = ApexInstrumentationService.processIfStatements(content, variableName);\n }\n\n if (content !== originalContent) {\n this.stats.modifiedFiles++;\n if (!isDryRun) {\n try {\n const finalContent = instrumentationOpts.prettier\n ? await ApexInstrumentationService.formatContent(content)\n : content;\n\n await fs.promises.writeFile(filePath, finalContent);\n\n if (instrumentationOpts.prettier) {\n this.stats.formattedFiles++;\n this.logger.info(`Modified and formatted: ${filePath}`);\n } else {\n this.logger.info(`Modified: ${filePath}`);\n }\n } catch (error) {\n this.logger.warn(`Failed to format ${filePath}: ${error instanceof Error ? error.message : String(error)}`);\n await fs.promises.writeFile(filePath, content);\n this.logger.info(`Modified without formatting: ${filePath}`);\n }\n } else {\n this.logger.info(`Would modify: ${filePath}`);\n }\n }\n } catch (error) {\n this.logger.error(`Error processing class ${className}`, error);\n throw error;\n }\n }\n}\n"]}
|