scancscode 1.0.35 → 1.0.36
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/.trae/specs/fix-string-expression-capture-range/checklist.md +7 -0
- package/.trae/specs/fix-string-expression-capture-range/spec.md +96 -0
- package/.trae/specs/fix-string-expression-capture-range/tasks.md +25 -0
- package/.trae/specs/handle-null-value/checklist.md +10 -0
- package/.trae/specs/handle-null-value/spec.md +57 -0
- package/.trae/specs/handle-null-value/tasks.md +40 -0
- package/.trae/specs/handle-right-value-expression/checklist.md +9 -0
- package/.trae/specs/handle-right-value-expression/spec.md +72 -0
- package/.trae/specs/handle-right-value-expression/tasks.md +53 -0
- package/.trae/specs/process-function-call-interpolated-strings/checklist.md +12 -0
- package/.trae/specs/process-function-call-interpolated-strings/spec.md +80 -0
- package/.trae/specs/process-function-call-interpolated-strings/tasks.md +73 -0
- package/dist/src/CSharpStringExtractor.js +547 -117
- package/dist/test/CSharpStringExtractor.test.js +174 -0
- package/package.json +1 -1
- package/src/CSharpStringExtractor.ts +581 -116
- package/test/CSharpStringExtractor.test.ts +185 -0
- package/dist/debug-arg.js +0 -30
- package/dist/debug-args.js +0 -34
- package/dist/debug-comment-5.js +0 -25
- package/dist/debug-comment-strings.js +0 -24
- package/dist/debug-full.js +0 -14
- package/dist/debug-template-issue.js +0 -33
- package/dist/debug-test-5.js +0 -23
- package/dist/debug-test.js +0 -21
- package/dist/debug.js +0 -15
- package/dist/simple-debug.js +0 -27
- package/dist/simple-test.js +0 -61
- package/dist/temp-original-source.js +0 -1
- package/dist/test-logic.js +0 -79
- package/dist/test-regex.js +0 -13
|
@@ -193,9 +193,16 @@ export class CSharpStringExtractor {
|
|
|
193
193
|
const trimmedStatement = statement.trim();
|
|
194
194
|
const isStringFormatCall = trimmedStatement.startsWith('string.Format(');
|
|
195
195
|
const isTextAssignment = /\w+\.text\s*=/.test(trimmedStatement);
|
|
196
|
-
const isRegularAssignment =
|
|
196
|
+
const isRegularAssignment = /^[\s\S]*?=/.test(trimmedStatement);
|
|
197
197
|
const isCaseOrDefault = trimmedStatement.startsWith('case ') || trimmedStatement.startsWith('default:');
|
|
198
198
|
const isFunctionCall = /^\s*[\w\.<>]+[\s\w\.<>]*\(/.test(trimmedStatement) && !isStringFormatCall && !isCaseOrDefault;
|
|
199
|
+
|
|
200
|
+
if ((isRegularAssignment && !isTextAssignment) && !isFunctionCall) {
|
|
201
|
+
const assignmentIndex = statement.indexOf('=');
|
|
202
|
+
if (assignmentIndex !== -1) {
|
|
203
|
+
this.processAllFunctionCallsInRange(originalIndex, originalIndex + assignmentIndex, code, snippets, trClass, trFormatMethod, trMethod);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
199
206
|
|
|
200
207
|
if (isFunctionCall && !isStringFormatCall) {
|
|
201
208
|
this.processFunctionCallArguments(statement, originalIndex, code, snippets, trClass, trFormatMethod, trMethod);
|
|
@@ -203,6 +210,8 @@ export class CSharpStringExtractor {
|
|
|
203
210
|
const extractionResult = this.extractValueExpression(statement, originalIndex, code);
|
|
204
211
|
const { valueExpression, valueExpressionIndex } = extractionResult;
|
|
205
212
|
|
|
213
|
+
const hasStringInValue = /"(?:[^"\\]|\\.)*"|'[^']*'|\$"[\s\S]*?"|\$@"[\s\S]*?"|@\$"[\s\S]*?"/.test(valueExpression);
|
|
214
|
+
|
|
206
215
|
let alreadyExists = false;
|
|
207
216
|
for (const snippet of snippets) {
|
|
208
217
|
if (snippet.originalIndex === valueExpressionIndex) {
|
|
@@ -211,7 +220,7 @@ export class CSharpStringExtractor {
|
|
|
211
220
|
}
|
|
212
221
|
}
|
|
213
222
|
|
|
214
|
-
if (!alreadyExists) {
|
|
223
|
+
if (!alreadyExists && (hasStringInValue || isTextAssignment)) {
|
|
215
224
|
const snippet = new CodeSnippet();
|
|
216
225
|
snippet.originalIndex = valueExpressionIndex;
|
|
217
226
|
snippet.originalCode = valueExpression;
|
|
@@ -219,7 +228,11 @@ export class CSharpStringExtractor {
|
|
|
219
228
|
|
|
220
229
|
this.variableIndex = 0;
|
|
221
230
|
|
|
222
|
-
|
|
231
|
+
if (isCaseOrDefault) {
|
|
232
|
+
this.processSingleArgument(snippet, valueExpression, trClass, trFormatMethod, trMethod);
|
|
233
|
+
} else {
|
|
234
|
+
this.processStatementAndExtractValue(snippet, statement, valueExpression, trClass, trFormatMethod, trMethod);
|
|
235
|
+
}
|
|
223
236
|
|
|
224
237
|
snippets.push(snippet);
|
|
225
238
|
}
|
|
@@ -265,6 +278,8 @@ export class CSharpStringExtractor {
|
|
|
265
278
|
let inClassBody = true;
|
|
266
279
|
let inComment = false;
|
|
267
280
|
let commentType = '';
|
|
281
|
+
let isInterpolatedString = false;
|
|
282
|
+
let interpolatedBraceDepth = 0;
|
|
268
283
|
|
|
269
284
|
for (j = braceOpenIndex + 1; j < code.length; j++) {
|
|
270
285
|
const char = code[j];
|
|
@@ -316,9 +331,11 @@ export class CSharpStringExtractor {
|
|
|
316
331
|
}
|
|
317
332
|
|
|
318
333
|
if (inString) {
|
|
319
|
-
if (char === stringDelimiter) {
|
|
334
|
+
if (char === stringDelimiter && (!isInterpolatedString || interpolatedBraceDepth === 0)) {
|
|
320
335
|
inString = false;
|
|
321
336
|
stringDelimiter = '';
|
|
337
|
+
isInterpolatedString = false;
|
|
338
|
+
interpolatedBraceDepth = 0;
|
|
322
339
|
|
|
323
340
|
if (afterEqual && braceDepth === 1) {
|
|
324
341
|
const stringLiteral = code.substring(stringStartPos, j + 1);
|
|
@@ -344,6 +361,12 @@ export class CSharpStringExtractor {
|
|
|
344
361
|
snippets.push(snippet);
|
|
345
362
|
}
|
|
346
363
|
}
|
|
364
|
+
} else if (isInterpolatedString) {
|
|
365
|
+
if (char === '{' && !escapeNext) {
|
|
366
|
+
interpolatedBraceDepth++;
|
|
367
|
+
} else if (char === '}' && !escapeNext && interpolatedBraceDepth > 0) {
|
|
368
|
+
interpolatedBraceDepth--;
|
|
369
|
+
}
|
|
347
370
|
}
|
|
348
371
|
continue;
|
|
349
372
|
}
|
|
@@ -351,12 +374,14 @@ export class CSharpStringExtractor {
|
|
|
351
374
|
if (!inString && afterEqual && braceDepth === 1 && j + 1 < code.length && char === '$') {
|
|
352
375
|
if (code[j + 1] === '"') {
|
|
353
376
|
inString = true;
|
|
377
|
+
isInterpolatedString = true;
|
|
354
378
|
stringDelimiter = '"';
|
|
355
379
|
stringStartPos = j;
|
|
356
380
|
j++;
|
|
357
381
|
continue;
|
|
358
382
|
} else if (code[j + 1] === '@' && j + 2 < code.length && code[j + 2] === '"') {
|
|
359
383
|
inString = true;
|
|
384
|
+
isInterpolatedString = true;
|
|
360
385
|
stringDelimiter = '"';
|
|
361
386
|
stringStartPos = j;
|
|
362
387
|
j += 2;
|
|
@@ -364,13 +389,15 @@ export class CSharpStringExtractor {
|
|
|
364
389
|
}
|
|
365
390
|
} else if (!inString && afterEqual && braceDepth === 1 && j + 1 < code.length && char === '@' && code[j + 1] === '$' && j + 2 < code.length && code[j + 2] === '"') {
|
|
366
391
|
inString = true;
|
|
392
|
+
isInterpolatedString = true;
|
|
367
393
|
stringDelimiter = '"';
|
|
368
394
|
stringStartPos = j;
|
|
369
395
|
j += 2;
|
|
370
396
|
continue;
|
|
371
|
-
} else if (!inString &&
|
|
397
|
+
} else if (!inString && char === '"') {
|
|
372
398
|
if (afterEqual && braceDepth === 1) {
|
|
373
399
|
inString = true;
|
|
400
|
+
isInterpolatedString = false;
|
|
374
401
|
stringDelimiter = char;
|
|
375
402
|
stringStartPos = j;
|
|
376
403
|
}
|
|
@@ -445,6 +472,8 @@ export class CSharpStringExtractor {
|
|
|
445
472
|
let commentType = '';
|
|
446
473
|
let inAnonymousFunction = false;
|
|
447
474
|
let anonymousFunctionBraceDepth = 0;
|
|
475
|
+
let isInterpolatedString = false;
|
|
476
|
+
let interpolatedBraceDepth = 0;
|
|
448
477
|
|
|
449
478
|
for (j = braceOpenIndex + 1; j < code.length; j++) {
|
|
450
479
|
const char = code[j];
|
|
@@ -503,9 +532,11 @@ export class CSharpStringExtractor {
|
|
|
503
532
|
}
|
|
504
533
|
|
|
505
534
|
if (inString) {
|
|
506
|
-
if (char === stringDelimiter) {
|
|
535
|
+
if (char === stringDelimiter && (!isInterpolatedString || interpolatedBraceDepth === 0)) {
|
|
507
536
|
inString = false;
|
|
508
537
|
stringDelimiter = '';
|
|
538
|
+
isInterpolatedString = false;
|
|
539
|
+
interpolatedBraceDepth = 0;
|
|
509
540
|
|
|
510
541
|
if (afterEqual || inAnonymousFunction) {
|
|
511
542
|
const stringLiteral = code.substring(stringStartPos, j + 1);
|
|
@@ -531,6 +562,12 @@ export class CSharpStringExtractor {
|
|
|
531
562
|
snippets.push(snippet);
|
|
532
563
|
}
|
|
533
564
|
}
|
|
565
|
+
} else if (isInterpolatedString) {
|
|
566
|
+
if (char === '{' && !escapeNext) {
|
|
567
|
+
interpolatedBraceDepth++;
|
|
568
|
+
} else if (char === '}' && !escapeNext && interpolatedBraceDepth > 0) {
|
|
569
|
+
interpolatedBraceDepth--;
|
|
570
|
+
}
|
|
534
571
|
}
|
|
535
572
|
continue;
|
|
536
573
|
}
|
|
@@ -538,12 +575,14 @@ export class CSharpStringExtractor {
|
|
|
538
575
|
if (!inString && (afterEqual || inAnonymousFunction) && j + 1 < code.length && char === '$') {
|
|
539
576
|
if (code[j + 1] === '"') {
|
|
540
577
|
inString = true;
|
|
578
|
+
isInterpolatedString = true;
|
|
541
579
|
stringDelimiter = '"';
|
|
542
580
|
stringStartPos = j;
|
|
543
581
|
j++;
|
|
544
582
|
continue;
|
|
545
583
|
} else if (code[j + 1] === '@' && j + 2 < code.length && code[j + 2] === '"') {
|
|
546
584
|
inString = true;
|
|
585
|
+
isInterpolatedString = true;
|
|
547
586
|
stringDelimiter = '"';
|
|
548
587
|
stringStartPos = j;
|
|
549
588
|
j += 2;
|
|
@@ -551,13 +590,15 @@ export class CSharpStringExtractor {
|
|
|
551
590
|
}
|
|
552
591
|
} else if (!inString && (afterEqual || inAnonymousFunction) && j + 1 < code.length && char === '@' && code[j + 1] === '$' && j + 2 < code.length && code[j + 2] === '"') {
|
|
553
592
|
inString = true;
|
|
593
|
+
isInterpolatedString = true;
|
|
554
594
|
stringDelimiter = '"';
|
|
555
595
|
stringStartPos = j;
|
|
556
596
|
j += 2;
|
|
557
597
|
continue;
|
|
558
|
-
} else if (!inString &&
|
|
598
|
+
} else if (!inString && char === '"') {
|
|
559
599
|
if (afterEqual || inAnonymousFunction) {
|
|
560
600
|
inString = true;
|
|
601
|
+
isInterpolatedString = false;
|
|
561
602
|
stringDelimiter = char;
|
|
562
603
|
stringStartPos = j;
|
|
563
604
|
}
|
|
@@ -611,12 +652,10 @@ private extractCommentStrings(code: string, snippets: CodeSnippet[], trClass: st
|
|
|
611
652
|
if (i + 1 < code.length && code[i] === '/' && code[i + 1] === '/') {
|
|
612
653
|
commentType = '//';
|
|
613
654
|
if (i + 2 < code.length && code[i + 2] === '/') {
|
|
614
|
-
// 这是文档注释(三个或更多连续 /),跳过它
|
|
615
655
|
isDocComment = true;
|
|
616
656
|
inComment = true;
|
|
617
657
|
i += 3;
|
|
618
658
|
} else {
|
|
619
|
-
// 普通注释,正常处理
|
|
620
659
|
inComment = true;
|
|
621
660
|
i += 2;
|
|
622
661
|
}
|
|
@@ -630,7 +669,6 @@ private extractCommentStrings(code: string, snippets: CodeSnippet[], trClass: st
|
|
|
630
669
|
}
|
|
631
670
|
|
|
632
671
|
if (isDocComment) {
|
|
633
|
-
// 对于文档注释,我们只需要跳过,不处理任何内容!
|
|
634
672
|
while (i < code.length && inComment) {
|
|
635
673
|
const char = code[i];
|
|
636
674
|
if (char === '\n') {
|
|
@@ -647,10 +685,12 @@ private extractCommentStrings(code: string, snippets: CodeSnippet[], trClass: st
|
|
|
647
685
|
let stringDelimiter = '';
|
|
648
686
|
let stringStartPos = -1;
|
|
649
687
|
let interpolatedBraceDepth = 0;
|
|
688
|
+
let isInterpolatedString = false;
|
|
650
689
|
|
|
651
690
|
while (i < code.length && inComment) {
|
|
652
691
|
const char = code[i];
|
|
653
692
|
const nextChar = i + 1 < code.length ? code[i + 1] : '';
|
|
693
|
+
const nextNextChar = i + 2 < code.length ? code[i + 2] : '';
|
|
654
694
|
|
|
655
695
|
if (commentType === '//') {
|
|
656
696
|
if (char === '\n') {
|
|
@@ -678,9 +718,11 @@ private extractCommentStrings(code: string, snippets: CodeSnippet[], trClass: st
|
|
|
678
718
|
}
|
|
679
719
|
|
|
680
720
|
if (inString) {
|
|
681
|
-
if (char === stringDelimiter) {
|
|
721
|
+
if (char === stringDelimiter && (!isInterpolatedString || interpolatedBraceDepth === 0)) {
|
|
682
722
|
inString = false;
|
|
683
723
|
stringDelimiter = '';
|
|
724
|
+
isInterpolatedString = false;
|
|
725
|
+
interpolatedBraceDepth = 0;
|
|
684
726
|
|
|
685
727
|
let alreadyExists = false;
|
|
686
728
|
for (const snippet of snippets) {
|
|
@@ -703,6 +745,12 @@ private extractCommentStrings(code: string, snippets: CodeSnippet[], trClass: st
|
|
|
703
745
|
|
|
704
746
|
snippets.push(snippet);
|
|
705
747
|
}
|
|
748
|
+
} else if (isInterpolatedString) {
|
|
749
|
+
if (char === '{' && !escapeNext) {
|
|
750
|
+
interpolatedBraceDepth++;
|
|
751
|
+
} else if (char === '}' && !escapeNext && interpolatedBraceDepth > 0) {
|
|
752
|
+
interpolatedBraceDepth--;
|
|
753
|
+
}
|
|
706
754
|
}
|
|
707
755
|
i++;
|
|
708
756
|
continue;
|
|
@@ -711,12 +759,14 @@ private extractCommentStrings(code: string, snippets: CodeSnippet[], trClass: st
|
|
|
711
759
|
if (!inString && i + 1 < code.length && char === '$') {
|
|
712
760
|
if (code[i + 1] === '"') {
|
|
713
761
|
inString = true;
|
|
762
|
+
isInterpolatedString = true;
|
|
714
763
|
stringDelimiter = '"';
|
|
715
764
|
stringStartPos = i;
|
|
716
765
|
i += 2;
|
|
717
766
|
continue;
|
|
718
767
|
} else if (code[i + 1] === '@' && i + 2 < code.length && code[i + 2] === '"') {
|
|
719
768
|
inString = true;
|
|
769
|
+
isInterpolatedString = true;
|
|
720
770
|
stringDelimiter = '"';
|
|
721
771
|
stringStartPos = i;
|
|
722
772
|
i += 3;
|
|
@@ -724,12 +774,14 @@ private extractCommentStrings(code: string, snippets: CodeSnippet[], trClass: st
|
|
|
724
774
|
}
|
|
725
775
|
} else if (!inString && i + 1 < code.length && char === '@' && code[i + 1] === '$' && i + 2 < code.length && code[i + 2] === '"') {
|
|
726
776
|
inString = true;
|
|
777
|
+
isInterpolatedString = true;
|
|
727
778
|
stringDelimiter = '"';
|
|
728
779
|
stringStartPos = i;
|
|
729
780
|
i += 3;
|
|
730
781
|
continue;
|
|
731
|
-
} else if (!inString &&
|
|
782
|
+
} else if (!inString && char === '"') {
|
|
732
783
|
inString = true;
|
|
784
|
+
isInterpolatedString = false;
|
|
733
785
|
stringDelimiter = char;
|
|
734
786
|
stringStartPos = i;
|
|
735
787
|
i++;
|
|
@@ -1872,12 +1924,15 @@ private findMatchingParenthesis(str: string, openIndex: number): number {
|
|
|
1872
1924
|
const textAssignmentRegex = /([\s\S]*?\.text\s*=\s*)([\s\S]*?)(?=;|$)/;
|
|
1873
1925
|
const match = textAssignmentRegex.exec(statement);
|
|
1874
1926
|
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
}
|
|
1927
|
+
let prefix: string | null = null;
|
|
1928
|
+
let value: string;
|
|
1878
1929
|
|
|
1879
|
-
|
|
1880
|
-
|
|
1930
|
+
if (match) {
|
|
1931
|
+
prefix = match[1];
|
|
1932
|
+
value = match[2];
|
|
1933
|
+
} else {
|
|
1934
|
+
value = statement;
|
|
1935
|
+
}
|
|
1881
1936
|
|
|
1882
1937
|
let processedValue = value;
|
|
1883
1938
|
|
|
@@ -1929,7 +1984,7 @@ private findMatchingParenthesis(str: string, openIndex: number): number {
|
|
|
1929
1984
|
} else {
|
|
1930
1985
|
const trimmedValue = value.trim();
|
|
1931
1986
|
if (!trimmedValue.includes(`${trClass}.${trFormatMethod}(`) && !trimmedValue.endsWith(`.${trMethod}()`)) {
|
|
1932
|
-
if (trimmedValue.startsWith('"') || /^\w+/.test(trimmedValue) || trimmedValue.startsWith('(')) {
|
|
1987
|
+
if (trimmedValue !== 'null' && (trimmedValue.startsWith('"') || /^\w+/.test(trimmedValue) || trimmedValue.startsWith('('))) {
|
|
1933
1988
|
const whitespaceBefore = value.substring(0, value.search(/\S/));
|
|
1934
1989
|
const actualValue = value.substring(value.search(/\S/));
|
|
1935
1990
|
const whitespaceAfter = actualValue.search(/\s*$/) === 0 ? actualValue : actualValue.substring(actualValue.search(/\S/) + trimmedValue.length);
|
|
@@ -1938,13 +1993,16 @@ private findMatchingParenthesis(str: string, openIndex: number): number {
|
|
|
1938
1993
|
}
|
|
1939
1994
|
}
|
|
1940
1995
|
|
|
1941
|
-
if (
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1996
|
+
if (prefix) {
|
|
1997
|
+
if (processedValue !== value) {
|
|
1998
|
+
const hasSemicolon = statement.trim().endsWith(';');
|
|
1999
|
+
const result = prefix + processedValue;
|
|
2000
|
+
return hasSemicolon ? result + ';' : result;
|
|
2001
|
+
}
|
|
2002
|
+
return statement;
|
|
2003
|
+
} else {
|
|
2004
|
+
return processedValue;
|
|
1945
2005
|
}
|
|
1946
|
-
|
|
1947
|
-
return statement;
|
|
1948
2006
|
}
|
|
1949
2007
|
|
|
1950
2008
|
private processStringConcatenation(statement: string, snippet: CodeSnippet, trClass: string, trFormatMethod: string, trMethod: string): string {
|
|
@@ -2011,12 +2069,62 @@ private findMatchingParenthesis(str: string, openIndex: number): number {
|
|
|
2011
2069
|
const hasSemicolon = statement.endsWith(';');
|
|
2012
2070
|
let statementWithoutSemicolon = hasSemicolon ? statement.slice(0, -1) : statement;
|
|
2013
2071
|
|
|
2014
|
-
|
|
2072
|
+
// Find actual assignment operator = that's not inside string, parentheses, etc.
|
|
2073
|
+
let assignmentIndex = -1;
|
|
2074
|
+
let tempInString = false;
|
|
2075
|
+
let tempEscapeNext = false;
|
|
2076
|
+
let tempStringDelimiter = '';
|
|
2077
|
+
let parenDepth = 0;
|
|
2078
|
+
let braceDepth = 0;
|
|
2079
|
+
let bracketDepth = 0;
|
|
2080
|
+
for (let i = 0; i < statementWithoutSemicolon.length; i++) {
|
|
2081
|
+
const char = statementWithoutSemicolon[i];
|
|
2082
|
+
if (tempEscapeNext) {
|
|
2083
|
+
tempEscapeNext = false;
|
|
2084
|
+
continue;
|
|
2085
|
+
}
|
|
2086
|
+
if (char === '\\') {
|
|
2087
|
+
tempEscapeNext = true;
|
|
2088
|
+
continue;
|
|
2089
|
+
}
|
|
2090
|
+
if (tempInString) {
|
|
2091
|
+
if (char === tempStringDelimiter) {
|
|
2092
|
+
tempInString = false;
|
|
2093
|
+
tempStringDelimiter = '';
|
|
2094
|
+
}
|
|
2095
|
+
continue;
|
|
2096
|
+
}
|
|
2097
|
+
if (char === '"' || char === "'") {
|
|
2098
|
+
tempInString = true;
|
|
2099
|
+
tempStringDelimiter = char;
|
|
2100
|
+
continue;
|
|
2101
|
+
}
|
|
2102
|
+
if (char === '(') {
|
|
2103
|
+
parenDepth++;
|
|
2104
|
+
} else if (char === ')') {
|
|
2105
|
+
parenDepth--;
|
|
2106
|
+
} else if (char === '{') {
|
|
2107
|
+
braceDepth++;
|
|
2108
|
+
} else if (char === '}') {
|
|
2109
|
+
braceDepth--;
|
|
2110
|
+
} else if (char === '[') {
|
|
2111
|
+
bracketDepth++;
|
|
2112
|
+
} else if (char === ']') {
|
|
2113
|
+
bracketDepth--;
|
|
2114
|
+
} else if (char === '=' && parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) {
|
|
2115
|
+
assignmentIndex = i;
|
|
2116
|
+
break;
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2015
2119
|
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2120
|
+
let leftSide = '';
|
|
2121
|
+
let rightSide = '';
|
|
2122
|
+
if (assignmentIndex !== -1) {
|
|
2123
|
+
leftSide = statementWithoutSemicolon.substring(0, assignmentIndex + 1); // Include =
|
|
2124
|
+
rightSide = statementWithoutSemicolon.substring(assignmentIndex + 1);
|
|
2125
|
+
}
|
|
2019
2126
|
|
|
2127
|
+
if (assignmentIndex !== -1) {
|
|
2020
2128
|
const parts = this.splitExpression(rightSide);
|
|
2021
2129
|
const processedParts: string[] = [];
|
|
2022
2130
|
|
|
@@ -2058,7 +2166,7 @@ private findMatchingParenthesis(str: string, openIndex: number): number {
|
|
|
2058
2166
|
const actualPart = part.substring(part.search(/\S/));
|
|
2059
2167
|
const whitespaceAfter = actualPart.search(/\s*$/) === 0 ? actualPart : actualPart.substring(actualPart.search(/\S/) + trimmedPart.length);
|
|
2060
2168
|
processedParts.push(whitespaceBefore + trimmedPart + `.${trMethod}()` + whitespaceAfter);
|
|
2061
|
-
} else if (trimmedPart && !trimmedPart.match(/^\s*$/) && !trimmedPart.match(/^\d+$/)) {
|
|
2169
|
+
} else if (trimmedPart !== 'null' && trimmedPart && !trimmedPart.match(/^\s*$/) && !trimmedPart.match(/^\d+$/)) {
|
|
2062
2170
|
const whitespaceBefore = part.substring(0, part.search(/\S/));
|
|
2063
2171
|
const actualPart = part.substring(part.search(/\S/));
|
|
2064
2172
|
const whitespaceAfter = actualPart.search(/\s*$/) === 0 ? actualPart : actualPart.substring(actualPart.search(/\S/) + trimmedPart.length);
|
|
@@ -2111,7 +2219,7 @@ private findMatchingParenthesis(str: string, openIndex: number): number {
|
|
|
2111
2219
|
const actualPart = part.substring(part.search(/\S/));
|
|
2112
2220
|
const whitespaceAfter = actualPart.search(/\s*$/) === 0 ? actualPart : actualPart.substring(actualPart.search(/\S/) + trimmedPart.length);
|
|
2113
2221
|
processedParts.push(whitespaceBefore + trimmedPart + `.${trMethod}()` + whitespaceAfter);
|
|
2114
|
-
} else if (trimmedPart && !trimmedPart.match(/^\s*$/) && !trimmedPart.match(/^\d+$/)) {
|
|
2222
|
+
} else if (trimmedPart !== 'null' && trimmedPart && !trimmedPart.match(/^\s*$/) && !trimmedPart.match(/^\d+$/)) {
|
|
2115
2223
|
if (trimmedPart.includes(`${trClass}.${trFormatMethod}(`)) {
|
|
2116
2224
|
processedParts.push(part);
|
|
2117
2225
|
continue;
|
|
@@ -2456,6 +2564,92 @@ private findMatchingParenthesis(str: string, openIndex: number): number {
|
|
|
2456
2564
|
}
|
|
2457
2565
|
}
|
|
2458
2566
|
|
|
2567
|
+
let startInStatement = -1;
|
|
2568
|
+
|
|
2569
|
+
for (let i = 0; i < statement.length - 1; i++) {
|
|
2570
|
+
const char = statement[i];
|
|
2571
|
+
const nextChar = i + 1 < statement.length ? statement[i + 1] : '';
|
|
2572
|
+
const nextNextChar = i + 2 < statement.length ? statement[i + 2] : '';
|
|
2573
|
+
|
|
2574
|
+
if ((char === '$' && nextChar === '"') ||
|
|
2575
|
+
(char === '$' && nextChar === '@' && nextNextChar === '"') ||
|
|
2576
|
+
(char === '@' && nextChar === '$' && nextNextChar === '"')) {
|
|
2577
|
+
startInStatement = i;
|
|
2578
|
+
break;
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
if (startInStatement === -1) {
|
|
2583
|
+
for (let i = 0; i < statement.length; i++) {
|
|
2584
|
+
if (statement[i] === '"' || statement[i] === "'") {
|
|
2585
|
+
startInStatement = i;
|
|
2586
|
+
break;
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
if (startInStatement !== -1) {
|
|
2592
|
+
const finalIndex = statementIndex + startInStatement;
|
|
2593
|
+
|
|
2594
|
+
let stringEnd = startInStatement;
|
|
2595
|
+
let inString = false;
|
|
2596
|
+
let escapeNext = false;
|
|
2597
|
+
let stringDelimiter = '';
|
|
2598
|
+
let interpolatedBraceDepth = 0;
|
|
2599
|
+
|
|
2600
|
+
let j = startInStatement;
|
|
2601
|
+
const char = statement[j];
|
|
2602
|
+
const nextChar = j + 1 < statement.length ? statement[j + 1] : '';
|
|
2603
|
+
const nextNextChar = j + 2 < statement.length ? statement[j + 2] : '';
|
|
2604
|
+
|
|
2605
|
+
if ((char === '$' && nextChar === '"')) {
|
|
2606
|
+
inString = true;
|
|
2607
|
+
stringDelimiter = '"';
|
|
2608
|
+
j += 2;
|
|
2609
|
+
} else if (char === '$' && nextChar === '@' && nextNextChar === '"') {
|
|
2610
|
+
inString = true;
|
|
2611
|
+
stringDelimiter = '"';
|
|
2612
|
+
j += 3;
|
|
2613
|
+
} else if (char === '@' && nextChar === '$' && nextNextChar === '"') {
|
|
2614
|
+
inString = true;
|
|
2615
|
+
stringDelimiter = '"';
|
|
2616
|
+
j += 3;
|
|
2617
|
+
} else if (char === '"' || char === "'") {
|
|
2618
|
+
inString = true;
|
|
2619
|
+
stringDelimiter = char;
|
|
2620
|
+
j++;
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
while (j < statement.length && inString) {
|
|
2624
|
+
const currentChar = statement[j];
|
|
2625
|
+
|
|
2626
|
+
if (escapeNext) {
|
|
2627
|
+
escapeNext = false;
|
|
2628
|
+
} else if (currentChar === '\\') {
|
|
2629
|
+
escapeNext = true;
|
|
2630
|
+
} else if (currentChar === stringDelimiter && interpolatedBraceDepth === 0) {
|
|
2631
|
+
inString = false;
|
|
2632
|
+
j++;
|
|
2633
|
+
stringEnd = j;
|
|
2634
|
+
break;
|
|
2635
|
+
} else if (currentChar === '{' && !escapeNext) {
|
|
2636
|
+
interpolatedBraceDepth++;
|
|
2637
|
+
} else if (currentChar === '}' && !escapeNext && interpolatedBraceDepth > 0) {
|
|
2638
|
+
interpolatedBraceDepth--;
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2641
|
+
j++;
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
if (!inString) {
|
|
2645
|
+
const valueExpression = statement.substring(startInStatement, stringEnd).trim();
|
|
2646
|
+
return {
|
|
2647
|
+
valueExpression,
|
|
2648
|
+
valueExpressionIndex: finalIndex
|
|
2649
|
+
};
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
|
|
2459
2653
|
return {
|
|
2460
2654
|
valueExpression: trimmedStatement,
|
|
2461
2655
|
valueExpressionIndex: statementIndex
|
|
@@ -2536,113 +2730,384 @@ private findMatchingParenthesis(str: string, openIndex: number): number {
|
|
|
2536
2730
|
}
|
|
2537
2731
|
|
|
2538
2732
|
private processStatementAndExtractValue(snippet: CodeSnippet, fullStatement: string, valueExpression: string, trClass: string, trFormatMethod: string, trMethod: string): void {
|
|
2539
|
-
let
|
|
2733
|
+
let processedValueExpression = valueExpression;
|
|
2734
|
+
const isTextAssignment = /\w+\.text\s*=/.test(fullStatement.trim());
|
|
2540
2735
|
|
|
2541
|
-
this.extractTrFormatStrings(
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2736
|
+
this.extractTrFormatStrings(processedValueExpression, snippet, trClass, trFormatMethod);
|
|
2737
|
+
processedValueExpression = this.processStringTemplates(processedValueExpression, snippet, trClass, trFormatMethod);
|
|
2738
|
+
processedValueExpression = this.processStringFormat(processedValueExpression, snippet, trClass, trFormatMethod);
|
|
2739
|
+
processedValueExpression = this.processStringConcatenation(processedValueExpression, snippet, trClass, trFormatMethod, trMethod);
|
|
2740
|
+
if (isTextAssignment) {
|
|
2741
|
+
processedValueExpression = this.processTextAssignments(processedValueExpression, snippet, trClass, trFormatMethod, trMethod);
|
|
2742
|
+
}
|
|
2743
|
+
this.extractPlainStrings(processedValueExpression, snippet, trClass, trFormatMethod);
|
|
2547
2744
|
|
|
2548
2745
|
const regex = new RegExp(`${trClass}\\.${trFormatMethod}\\(([^)]*)\\)\\.${trMethod}\\(\\)`, 'g');
|
|
2549
|
-
|
|
2746
|
+
processedValueExpression = processedValueExpression.replace(regex, `${trClass}.${trFormatMethod}($1)`);
|
|
2550
2747
|
snippet.finalizeLiterals();
|
|
2551
2748
|
|
|
2552
|
-
let convertedValueExpression =
|
|
2749
|
+
let convertedValueExpression = processedValueExpression;
|
|
2553
2750
|
|
|
2554
|
-
|
|
2555
|
-
|
|
2751
|
+
if (convertedValueExpression.endsWith(';')) {
|
|
2752
|
+
convertedValueExpression = convertedValueExpression.slice(0, -1).trim();
|
|
2753
|
+
}
|
|
2556
2754
|
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2755
|
+
snippet.convertedCode = convertedValueExpression;
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
private processAllFunctionCallsInRange(startIndex: number, endIndex: number, fullCode: string, snippets: CodeSnippet[], trClass: string, trFormatMethod: string, trMethod: string): void {
|
|
2759
|
+
let i = startIndex;
|
|
2760
|
+
while (i < endIndex) {
|
|
2761
|
+
let actualParenOpenIndex = -1;
|
|
2762
|
+
let tempDepth = 0;
|
|
2763
|
+
let tempInString = false;
|
|
2764
|
+
let tempEscapeNext = false;
|
|
2765
|
+
let tempStringDelimiter = '';
|
|
2766
|
+
let isStringFormat = false;
|
|
2767
|
+
let functionNameStart = -1;
|
|
2768
|
+
|
|
2769
|
+
for (let j = i; j < endIndex; j++) {
|
|
2770
|
+
const char = fullCode[j];
|
|
2771
|
+
const nextChar = j + 1 < fullCode.length ? fullCode[j + 1] : '';
|
|
2772
|
+
const nextNextChar = j + 2 < fullCode.length ? fullCode[j + 2] : '';
|
|
2773
|
+
|
|
2774
|
+
if (tempEscapeNext) {
|
|
2775
|
+
tempEscapeNext = false;
|
|
2776
|
+
continue;
|
|
2572
2777
|
}
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
if (textAssignmentIndex !== -1) {
|
|
2578
|
-
if (fullStatement === processedFullStatement) {
|
|
2579
|
-
convertedValueExpression = valueExpression;
|
|
2580
|
-
} else {
|
|
2581
|
-
const prefix = trimmedFullStatement.substring(0, textAssignmentIndex + '.text ='.length);
|
|
2582
|
-
const valuePart = trimmedProcessedStatement.substring(textAssignmentIndex + '.text ='.length);
|
|
2583
|
-
const value = this.extractValueUntilSemicolon(valuePart);
|
|
2584
|
-
convertedValueExpression = value.trim();
|
|
2778
|
+
|
|
2779
|
+
if (char === '\\') {
|
|
2780
|
+
tempEscapeNext = true;
|
|
2781
|
+
continue;
|
|
2585
2782
|
}
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2783
|
+
|
|
2784
|
+
if (tempInString) {
|
|
2785
|
+
if (char === tempStringDelimiter) {
|
|
2786
|
+
tempInString = false;
|
|
2787
|
+
tempStringDelimiter = '';
|
|
2788
|
+
}
|
|
2789
|
+
continue;
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
if ((char === '$' && nextChar === '"') ||
|
|
2793
|
+
(char === '$' && nextChar === '@' && nextNextChar === '"') ||
|
|
2794
|
+
(char === '@' && nextChar === '$' && nextNextChar === '"')) {
|
|
2795
|
+
tempInString = true;
|
|
2796
|
+
tempStringDelimiter = '"';
|
|
2797
|
+
if (nextChar === '@') {
|
|
2798
|
+
j += 2;
|
|
2591
2799
|
} else {
|
|
2592
|
-
|
|
2593
|
-
const valuePart = trimmedProcessedStatement.substring(assignmentIndex + 1);
|
|
2594
|
-
const value = this.extractValueUntilSemicolon(valuePart);
|
|
2595
|
-
convertedValueExpression = value.trim();
|
|
2800
|
+
j += 1;
|
|
2596
2801
|
}
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2802
|
+
continue;
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2805
|
+
if (char === '"' || char === "'") {
|
|
2806
|
+
tempInString = true;
|
|
2807
|
+
tempStringDelimiter = char;
|
|
2808
|
+
continue;
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
if (char === '(') {
|
|
2812
|
+
tempDepth++;
|
|
2813
|
+
if (actualParenOpenIndex === -1) {
|
|
2814
|
+
actualParenOpenIndex = j;
|
|
2815
|
+
if (functionNameStart !== -1) {
|
|
2816
|
+
const funcName = fullCode.substring(functionNameStart, j).trim();
|
|
2817
|
+
isStringFormat = funcName === 'string.Format';
|
|
2818
|
+
}
|
|
2601
2819
|
}
|
|
2602
|
-
} else if (
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2820
|
+
} else if (char === ')') {
|
|
2821
|
+
tempDepth--;
|
|
2822
|
+
if (tempDepth === 0 && actualParenOpenIndex !== -1 && !isStringFormat) {
|
|
2823
|
+
const actualParenCloseIndex = j;
|
|
2824
|
+
let currentSnippetCount = 0;
|
|
2825
|
+
const stringLiteralPositions: number[] = [];
|
|
2826
|
+
|
|
2827
|
+
let k = actualParenOpenIndex;
|
|
2828
|
+
let inString3 = false;
|
|
2829
|
+
let escapeNext3 = false;
|
|
2830
|
+
let stringDelimiter3 = '';
|
|
2831
|
+
let stringStart = -1;
|
|
2832
|
+
|
|
2833
|
+
while (k < fullCode.length && k <= actualParenCloseIndex) {
|
|
2834
|
+
const char = fullCode[k];
|
|
2835
|
+
const nextChar = k + 1 < fullCode.length ? fullCode[k + 1] : '';
|
|
2836
|
+
const nextNextChar = k + 2 < fullCode.length ? fullCode[k + 2] : '';
|
|
2837
|
+
|
|
2838
|
+
if (escapeNext3) {
|
|
2839
|
+
escapeNext3 = false;
|
|
2840
|
+
k++;
|
|
2841
|
+
continue;
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
if (char === '\\') {
|
|
2845
|
+
escapeNext3 = true;
|
|
2846
|
+
k++;
|
|
2847
|
+
continue;
|
|
2848
|
+
}
|
|
2849
|
+
|
|
2850
|
+
if (inString3) {
|
|
2851
|
+
if (char === stringDelimiter3) {
|
|
2852
|
+
stringLiteralPositions.push(stringStart);
|
|
2853
|
+
inString3 = false;
|
|
2854
|
+
stringDelimiter3 = '';
|
|
2855
|
+
}
|
|
2856
|
+
k++;
|
|
2857
|
+
continue;
|
|
2614
2858
|
}
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2859
|
+
|
|
2860
|
+
if ((char === '$' && nextChar === '"') ||
|
|
2861
|
+
(char === '$' && nextChar === '@' && nextNextChar === '"') ||
|
|
2862
|
+
(char === '@' && nextChar === '$' && nextNextChar === '"')) {
|
|
2863
|
+
inString3 = true;
|
|
2864
|
+
stringDelimiter3 = '"';
|
|
2865
|
+
stringStart = k;
|
|
2866
|
+
if (nextChar === '@') {
|
|
2867
|
+
k += 2;
|
|
2621
2868
|
} else {
|
|
2622
|
-
|
|
2869
|
+
k += 1;
|
|
2623
2870
|
}
|
|
2624
|
-
|
|
2625
|
-
convertedValueExpression = valueExpression;
|
|
2871
|
+
continue;
|
|
2626
2872
|
}
|
|
2873
|
+
|
|
2874
|
+
if (char === '"' || char === "'") {
|
|
2875
|
+
inString3 = true;
|
|
2876
|
+
stringDelimiter3 = char;
|
|
2877
|
+
stringStart = k;
|
|
2878
|
+
k++;
|
|
2879
|
+
continue;
|
|
2880
|
+
}
|
|
2881
|
+
|
|
2882
|
+
if (char === ')' && k === actualParenCloseIndex) {
|
|
2883
|
+
break;
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
k++;
|
|
2627
2887
|
}
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
const
|
|
2633
|
-
|
|
2634
|
-
|
|
2888
|
+
|
|
2889
|
+
let argStartPos = actualParenOpenIndex + 1;
|
|
2890
|
+
|
|
2891
|
+
const trimmedCode = fullCode.substring(actualParenOpenIndex + 1, actualParenCloseIndex);
|
|
2892
|
+
const args = this.splitArguments(trimmedCode);
|
|
2893
|
+
|
|
2894
|
+
for (const arg of args) {
|
|
2895
|
+
const trimmedArg = arg.trim();
|
|
2896
|
+
if (!trimmedArg) {
|
|
2897
|
+
argStartPos = this.updateArgStartPos(argStartPos, fullCode, actualParenCloseIndex);
|
|
2898
|
+
continue;
|
|
2899
|
+
}
|
|
2900
|
+
|
|
2901
|
+
const hasStringLiteral = /"(?:[^"\\]|\\.)*"/.test(trimmedArg) ||
|
|
2902
|
+
/\$"[\s\S]*?"/.test(trimmedArg) ||
|
|
2903
|
+
/\$@"[\s\S]*?"/.test(trimmedArg) ||
|
|
2904
|
+
/@\$"[\s\S]*?"/.test(trimmedArg);
|
|
2905
|
+
|
|
2906
|
+
while (argStartPos < fullCode.length && /\s/.test(fullCode[argStartPos])) {
|
|
2907
|
+
argStartPos++;
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
let foundArgEnd = argStartPos;
|
|
2911
|
+
let inString4 = false;
|
|
2912
|
+
let escapeNext4 = false;
|
|
2913
|
+
let stringDelimiter4 = '';
|
|
2914
|
+
let parenthesesDepth = 0;
|
|
2915
|
+
let braceDepth = 0;
|
|
2916
|
+
let bracketDepth = 0;
|
|
2917
|
+
|
|
2918
|
+
while (foundArgEnd < fullCode.length && foundArgEnd <= actualParenCloseIndex) {
|
|
2919
|
+
const char = fullCode[foundArgEnd];
|
|
2920
|
+
const nextChar = foundArgEnd + 1 < fullCode.length ? fullCode[foundArgEnd + 1] : '';
|
|
2921
|
+
const nextNextChar = foundArgEnd + 2 < fullCode.length ? fullCode[foundArgEnd + 2] : '';
|
|
2922
|
+
|
|
2923
|
+
if (escapeNext4) {
|
|
2924
|
+
escapeNext4 = false;
|
|
2925
|
+
foundArgEnd++;
|
|
2926
|
+
continue;
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
if (char === '\\') {
|
|
2930
|
+
escapeNext4 = true;
|
|
2931
|
+
foundArgEnd++;
|
|
2932
|
+
continue;
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2935
|
+
if (inString4) {
|
|
2936
|
+
if (char === stringDelimiter4) {
|
|
2937
|
+
inString4 = false;
|
|
2938
|
+
stringDelimiter4 = '';
|
|
2939
|
+
}
|
|
2940
|
+
foundArgEnd++;
|
|
2941
|
+
continue;
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
if ((char === '$' && nextChar === '"') ||
|
|
2945
|
+
(char === '$' && nextChar === '@' && nextNextChar === '"') ||
|
|
2946
|
+
(char === '@' && nextChar === '$' && nextNextChar === '"')) {
|
|
2947
|
+
inString4 = true;
|
|
2948
|
+
stringDelimiter4 = '"';
|
|
2949
|
+
if (nextChar === '@') {
|
|
2950
|
+
foundArgEnd += 2;
|
|
2951
|
+
} else {
|
|
2952
|
+
foundArgEnd += 1;
|
|
2953
|
+
}
|
|
2954
|
+
continue;
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
if (char === '"' || char === "'") {
|
|
2958
|
+
inString4 = true;
|
|
2959
|
+
stringDelimiter4 = char;
|
|
2960
|
+
foundArgEnd++;
|
|
2961
|
+
continue;
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2964
|
+
if (char === '(') {
|
|
2965
|
+
parenthesesDepth++;
|
|
2966
|
+
} else if (char === ')') {
|
|
2967
|
+
if (foundArgEnd === actualParenCloseIndex) {
|
|
2968
|
+
break;
|
|
2969
|
+
}
|
|
2970
|
+
parenthesesDepth--;
|
|
2971
|
+
} else if (char === '{') {
|
|
2972
|
+
braceDepth++;
|
|
2973
|
+
} else if (char === '}') {
|
|
2974
|
+
braceDepth--;
|
|
2975
|
+
} else if (char === '[') {
|
|
2976
|
+
bracketDepth++;
|
|
2977
|
+
} else if (char === ']') {
|
|
2978
|
+
bracketDepth--;
|
|
2979
|
+
} else if (char === ',' && parenthesesDepth === 0 && braceDepth === 0 && bracketDepth === 0) {
|
|
2980
|
+
break;
|
|
2981
|
+
}
|
|
2982
|
+
|
|
2983
|
+
foundArgEnd++;
|
|
2984
|
+
}
|
|
2985
|
+
|
|
2986
|
+
if (!hasStringLiteral) {
|
|
2987
|
+
argStartPos = foundArgEnd + 1;
|
|
2988
|
+
continue;
|
|
2989
|
+
}
|
|
2990
|
+
|
|
2991
|
+
const actualArg = fullCode.substring(argStartPos, foundArgEnd).trim();
|
|
2992
|
+
|
|
2993
|
+
const isObjectInitializer = actualArg.startsWith('new ') && actualArg.includes('{') && actualArg.includes('}');
|
|
2994
|
+
|
|
2995
|
+
if (isObjectInitializer) {
|
|
2996
|
+
this.processObjectInitializerStringsOnly(argStartPos, fullCode, snippets, trClass, trFormatMethod, trMethod);
|
|
2997
|
+
} else {
|
|
2998
|
+
let finalOriginalIndex = argStartPos;
|
|
2999
|
+
|
|
3000
|
+
if (currentSnippetCount < stringLiteralPositions.length) {
|
|
3001
|
+
finalOriginalIndex = stringLiteralPositions[currentSnippetCount];
|
|
3002
|
+
}
|
|
3003
|
+
|
|
3004
|
+
let alreadyExists = false;
|
|
3005
|
+
for (const snippet of snippets) {
|
|
3006
|
+
if (snippet.originalIndex === finalOriginalIndex) {
|
|
3007
|
+
alreadyExists = true;
|
|
3008
|
+
break;
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
if (!alreadyExists) {
|
|
3013
|
+
let finalArg = actualArg;
|
|
3014
|
+
|
|
3015
|
+
if (currentSnippetCount < stringLiteralPositions.length) {
|
|
3016
|
+
const stringStart = stringLiteralPositions[currentSnippetCount];
|
|
3017
|
+
let stringEnd = stringStart;
|
|
3018
|
+
|
|
3019
|
+
let j = stringStart;
|
|
3020
|
+
let inString = false;
|
|
3021
|
+
let escapeNext = false;
|
|
3022
|
+
let stringDelimiter = '';
|
|
3023
|
+
let braceDepth = 0;
|
|
3024
|
+
let interpolatedBraceDepth = 0;
|
|
3025
|
+
|
|
3026
|
+
const char = fullCode[j];
|
|
3027
|
+
const nextChar = j + 1 < fullCode.length ? fullCode[j + 1] : '';
|
|
3028
|
+
const nextNextChar = j + 2 < fullCode.length ? fullCode[j + 2] : '';
|
|
3029
|
+
|
|
3030
|
+
if ((char === '$' && nextChar === '"')) {
|
|
3031
|
+
inString = true;
|
|
3032
|
+
stringDelimiter = '"';
|
|
3033
|
+
j += 2;
|
|
3034
|
+
} else if (char === '$' && nextChar === '@' && j + 2 < fullCode.length && fullCode[j + 2] === '"') {
|
|
3035
|
+
inString = true;
|
|
3036
|
+
stringDelimiter = '"';
|
|
3037
|
+
j += 3;
|
|
3038
|
+
} else if (char === '@' && nextChar === '$' && j + 2 < fullCode.length && fullCode[j + 2] === '"') {
|
|
3039
|
+
inString = true;
|
|
3040
|
+
stringDelimiter = '"';
|
|
3041
|
+
j += 3;
|
|
3042
|
+
} else if (char === '"' || char === "'") {
|
|
3043
|
+
inString = true;
|
|
3044
|
+
stringDelimiter = char;
|
|
3045
|
+
j++;
|
|
3046
|
+
}
|
|
3047
|
+
|
|
3048
|
+
while (j < fullCode.length && inString) {
|
|
3049
|
+
const currentChar = fullCode[j];
|
|
3050
|
+
|
|
3051
|
+
if (escapeNext) {
|
|
3052
|
+
escapeNext = false;
|
|
3053
|
+
} else if (currentChar === '\\') {
|
|
3054
|
+
escapeNext = true;
|
|
3055
|
+
} else if (currentChar === stringDelimiter && interpolatedBraceDepth === 0) {
|
|
3056
|
+
inString = false;
|
|
3057
|
+
j++;
|
|
3058
|
+
stringEnd = j;
|
|
3059
|
+
break;
|
|
3060
|
+
} else if (currentChar === '{' && !escapeNext) {
|
|
3061
|
+
interpolatedBraceDepth++;
|
|
3062
|
+
} else if (currentChar === '}' && !escapeNext && interpolatedBraceDepth > 0) {
|
|
3063
|
+
interpolatedBraceDepth--;
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
j++;
|
|
3067
|
+
}
|
|
3068
|
+
|
|
3069
|
+
if (!inString) {
|
|
3070
|
+
finalArg = fullCode.substring(stringStart, stringEnd);
|
|
3071
|
+
}
|
|
3072
|
+
}
|
|
3073
|
+
|
|
3074
|
+
const snippet = new CodeSnippet();
|
|
3075
|
+
snippet.originalIndex = finalOriginalIndex;
|
|
3076
|
+
snippet.originalCode = finalArg;
|
|
3077
|
+
snippet.originalContext = finalArg;
|
|
3078
|
+
|
|
3079
|
+
this.variableIndex = 0;
|
|
3080
|
+
|
|
3081
|
+
this.processSingleArgument(snippet, finalArg, trClass, trFormatMethod, trMethod);
|
|
3082
|
+
|
|
3083
|
+
snippets.push(snippet);
|
|
3084
|
+
currentSnippetCount++;
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
|
|
3088
|
+
argStartPos = foundArgEnd + 1;
|
|
2635
3089
|
}
|
|
3090
|
+
|
|
3091
|
+
i = actualParenCloseIndex + 1;
|
|
3092
|
+
actualParenOpenIndex = -1;
|
|
3093
|
+
isStringFormat = false;
|
|
3094
|
+
functionNameStart = -1;
|
|
3095
|
+
} else if (tempDepth === 0 && actualParenOpenIndex !== -1 && isStringFormat) {
|
|
3096
|
+
i = j + 1;
|
|
3097
|
+
actualParenOpenIndex = -1;
|
|
3098
|
+
isStringFormat = false;
|
|
3099
|
+
functionNameStart = -1;
|
|
2636
3100
|
}
|
|
2637
|
-
} else {
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
}
|
|
3101
|
+
} else if (!tempInString && char === '.' && tempDepth === 0) {
|
|
3102
|
+
functionNameStart = -1;
|
|
3103
|
+
} else if (!tempInString && /[a-zA-Z_]/.test(char) && tempDepth === 0 && functionNameStart === -1) {
|
|
3104
|
+
functionNameStart = j;
|
|
2642
3105
|
}
|
|
2643
3106
|
}
|
|
3107
|
+
|
|
3108
|
+
if (actualParenOpenIndex === -1) {
|
|
3109
|
+
break;
|
|
3110
|
+
}
|
|
2644
3111
|
}
|
|
2645
|
-
|
|
2646
|
-
snippet.convertedCode = convertedValueExpression;
|
|
2647
3112
|
}
|
|
2648
3113
|
}
|