@nielspeter/sonarlint-mcp-server 0.4.0 → 0.5.0
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/CHANGELOG.md +24 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +10 -4
- package/dist/errors.js.map +1 -1
- package/dist/index.js +68 -49
- package/dist/index.js.map +1 -1
- package/dist/resources/session.d.ts +1 -1
- package/dist/resources/session.d.ts.map +1 -1
- package/dist/resources/session.js +22 -18
- package/dist/resources/session.js.map +1 -1
- package/dist/sloop-bridge.d.ts +14 -0
- package/dist/sloop-bridge.d.ts.map +1 -1
- package/dist/sloop-bridge.js +103 -89
- package/dist/sloop-bridge.js.map +1 -1
- package/dist/state.d.ts +2 -3
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +2 -2
- package/dist/state.js.map +1 -1
- package/dist/tools/analyze-content.d.ts.map +1 -1
- package/dist/tools/analyze-content.js +17 -17
- package/dist/tools/analyze-content.js.map +1 -1
- package/dist/tools/analyze-file.d.ts.map +1 -1
- package/dist/tools/analyze-file.js +16 -18
- package/dist/tools/analyze-file.js.map +1 -1
- package/dist/tools/analyze-files.d.ts.map +1 -1
- package/dist/tools/analyze-files.js +71 -96
- package/dist/tools/analyze-files.js.map +1 -1
- package/dist/tools/apply-all-quick-fixes.d.ts.map +1 -1
- package/dist/tools/apply-all-quick-fixes.js +71 -141
- package/dist/tools/apply-all-quick-fixes.js.map +1 -1
- package/dist/tools/apply-quick-fix.d.ts.map +1 -1
- package/dist/tools/apply-quick-fix.js +13 -84
- package/dist/tools/apply-quick-fix.js.map +1 -1
- package/dist/tools/health-check.d.ts.map +1 -1
- package/dist/tools/health-check.js +30 -22
- package/dist/tools/health-check.js.map +1 -1
- package/dist/tools/list-active-rules.d.ts.map +1 -1
- package/dist/tools/list-active-rules.js +25 -15
- package/dist/tools/list-active-rules.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils/config.d.ts +32 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +54 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/file-registration.d.ts.map +1 -1
- package/dist/utils/file-registration.js +2 -2
- package/dist/utils/file-registration.js.map +1 -1
- package/dist/utils/filesystem.js +8 -8
- package/dist/utils/filesystem.js.map +1 -1
- package/dist/utils/formatting.d.ts +1 -1
- package/dist/utils/formatting.d.ts.map +1 -1
- package/dist/utils/formatting.js +2 -4
- package/dist/utils/formatting.js.map +1 -1
- package/dist/utils/language.js +11 -11
- package/dist/utils/language.js.map +1 -1
- package/dist/utils/quick-fix.d.ts +14 -0
- package/dist/utils/quick-fix.d.ts.map +1 -0
- package/dist/utils/quick-fix.js +48 -0
- package/dist/utils/quick-fix.js.map +1 -0
- package/dist/utils/scope.d.ts +4 -0
- package/dist/utils/scope.d.ts.map +1 -1
- package/dist/utils/scope.js +8 -7
- package/dist/utils/scope.js.map +1 -1
- package/dist/utils/sloop.d.ts +4 -3
- package/dist/utils/sloop.d.ts.map +1 -1
- package/dist/utils/sloop.js +22 -13
- package/dist/utils/sloop.js.map +1 -1
- package/dist/utils/transforms.d.ts +1 -1
- package/dist/utils/transforms.d.ts.map +1 -1
- package/dist/utils/transforms.js.map +1 -1
- package/package.json +12 -2
- package/scripts/generate-rules-doc.mjs +86 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { existsSync } from
|
|
2
|
-
import { extname } from
|
|
3
|
-
import { SloopError } from
|
|
4
|
-
import { ensureSloopBridge } from
|
|
5
|
-
import { getOrCreateScope } from
|
|
6
|
-
import { detectLanguage } from
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { extname } from 'path';
|
|
3
|
+
import { SloopError } from '../errors.js';
|
|
4
|
+
import { ensureSloopBridge } from '../utils/sloop.js';
|
|
5
|
+
import { getOrCreateScope } from '../utils/scope.js';
|
|
6
|
+
import { detectLanguage } from '../utils/language.js';
|
|
7
|
+
import { filterBySeverity } from '../utils/quick-fix.js';
|
|
8
|
+
import { transformSloopIssues, createSummary } from '../utils/transforms.js';
|
|
9
|
+
import { formatAnalysisResult } from '../utils/formatting.js';
|
|
10
|
+
import { sessionResults } from '../state.js';
|
|
10
11
|
export async function handleAnalyzeFile(args) {
|
|
11
12
|
const { filePath, minSeverity, excludeRules } = args;
|
|
12
13
|
// Validate file exists
|
|
@@ -20,7 +21,7 @@ export async function handleAnalyzeFile(args) {
|
|
|
20
21
|
throw new SloopError(`Unknown language for ${filePath}`, `No analyzer available for ${ext} files. Supported extensions: .js, .jsx, .ts, .tsx, .py, .java, .go, .php, .rb, .html, .css, .xml`, false);
|
|
21
22
|
}
|
|
22
23
|
// Ensure SLOOP is initialized
|
|
23
|
-
const bridge = await ensureSloopBridge();
|
|
24
|
+
const bridge = await ensureSloopBridge(filePath);
|
|
24
25
|
// Get or create scope
|
|
25
26
|
const scopeId = await getOrCreateScope(filePath);
|
|
26
27
|
console.error(`[MCP] Analyzing file: ${filePath}`);
|
|
@@ -30,25 +31,22 @@ export async function handleAnalyzeFile(args) {
|
|
|
30
31
|
const rawResult = await bridge.analyzeFilesAndTrack(scopeId, [filePath]);
|
|
31
32
|
console.error(`[MCP] analyzeFilesAndTrack returned`);
|
|
32
33
|
// Extract issues: prefer raisedIssues (from notifications) over rawIssues (from response)
|
|
33
|
-
const rawIssues = rawResult.raisedIssues?.length ? rawResult.raisedIssues :
|
|
34
|
+
const rawIssues = rawResult.raisedIssues?.length ? rawResult.raisedIssues : rawResult.rawIssues || [];
|
|
34
35
|
console.error(`[MCP] Found ${rawIssues.length} issues (source: ${rawResult.raisedIssues?.length ? 'raiseIssues notification' : 'response'})`);
|
|
35
36
|
// Transform to simplified format
|
|
36
37
|
let issues = transformSloopIssues(rawIssues);
|
|
37
|
-
// Apply filtering if requested
|
|
38
38
|
if (minSeverity) {
|
|
39
|
-
|
|
40
|
-
const minLevel = severityOrder[minSeverity];
|
|
41
|
-
issues = issues.filter(issue => (severityOrder[issue.severity] || 0) >= minLevel);
|
|
39
|
+
issues = filterBySeverity(issues, minSeverity);
|
|
42
40
|
}
|
|
43
41
|
if (excludeRules && excludeRules.length > 0) {
|
|
44
|
-
issues = issues.filter(issue => !excludeRules.includes(issue.rule));
|
|
42
|
+
issues = issues.filter((issue) => !excludeRules.includes(issue.rule));
|
|
45
43
|
}
|
|
46
44
|
// Create result
|
|
47
45
|
const result = {
|
|
48
46
|
filePath,
|
|
49
47
|
language,
|
|
50
48
|
issues,
|
|
51
|
-
summary: createSummary(issues, 265),
|
|
49
|
+
summary: createSummary(issues, 265),
|
|
52
50
|
};
|
|
53
51
|
// Store in session for MCP resources
|
|
54
52
|
sessionResults.set(filePath, result);
|
|
@@ -57,7 +55,7 @@ export async function handleAnalyzeFile(args) {
|
|
|
57
55
|
return {
|
|
58
56
|
content: [
|
|
59
57
|
{
|
|
60
|
-
type:
|
|
58
|
+
type: 'text',
|
|
61
59
|
text: formattedResult,
|
|
62
60
|
},
|
|
63
61
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-file.js","sourceRoot":"","sources":["../../src/tools/analyze-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAS;IAC/C,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,IAI/C,CAAC;IAEF,uBAAuB;IACvB,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAClB,mBAAmB,QAAQ,EAAE,EAC7B,YAAY,QAAQ,uDAAuD,EAC3E,KAAK,CACN,CAAC;IACJ,CAAC;IAED,kBAAkB;IAClB,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,IAAI,UAAU,CAClB,wBAAwB,QAAQ,EAAE,EAClC,6BAA6B,GAAG,mGAAmG,EACnI,KAAK,CACN,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,MAAM,MAAM,GAAG,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"analyze-file.js","sourceRoot":"","sources":["../../src/tools/analyze-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-files.d.ts","sourceRoot":"","sources":["../../src/tools/analyze-files.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analyze-files.d.ts","sourceRoot":"","sources":["../../src/tools/analyze-files.ts"],"names":[],"mappings":"AAwGA,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,GAAG;;;;;GAyDjD"}
|
|
@@ -1,54 +1,51 @@
|
|
|
1
|
-
import { existsSync } from
|
|
2
|
-
import { createRequire } from
|
|
3
|
-
import { resolve } from
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import { resolve } from 'path';
|
|
4
4
|
// globSync is available in Node 22+ but @types/node doesn't export it yet
|
|
5
5
|
const require = createRequire(import.meta.url);
|
|
6
|
-
const { globSync } = require(
|
|
7
|
-
import { SloopError } from
|
|
8
|
-
import { ensureSloopBridge } from
|
|
9
|
-
import { getOrCreateScope } from
|
|
10
|
-
import { detectLanguage } from
|
|
11
|
-
import { transformSloopIssues } from
|
|
12
|
-
import { formatBatchAnalysisResult } from
|
|
13
|
-
import {
|
|
6
|
+
const { globSync } = require('fs');
|
|
7
|
+
import { SloopError } from '../errors.js';
|
|
8
|
+
import { ensureSloopBridge } from '../utils/sloop.js';
|
|
9
|
+
import { getOrCreateScope } from '../utils/scope.js';
|
|
10
|
+
import { detectLanguage } from '../utils/language.js';
|
|
11
|
+
import { transformSloopIssues } from '../utils/transforms.js';
|
|
12
|
+
import { formatBatchAnalysisResult } from '../utils/formatting.js';
|
|
13
|
+
import { filterBySeverity } from '../utils/quick-fix.js';
|
|
14
|
+
import { batchResults } from '../state.js';
|
|
14
15
|
/**
|
|
15
|
-
* Expand glob patterns
|
|
16
|
-
*
|
|
16
|
+
* Expand glob patterns and resolve relative paths against basePath.
|
|
17
|
+
* Absolute paths/globs are used as-is; relative ones need basePath.
|
|
17
18
|
*/
|
|
18
|
-
function expandGlobs(paths) {
|
|
19
|
+
function expandGlobs(paths, basePath) {
|
|
19
20
|
const result = [];
|
|
20
21
|
for (const p of paths) {
|
|
22
|
+
const isRelative = !p.startsWith('/');
|
|
23
|
+
if (isRelative && !basePath) {
|
|
24
|
+
throw new SloopError(`Relative path requires basePath: ${p}`, `Relative paths need a basePath to resolve against. Provide basePath (the project root) or use absolute paths.`, false);
|
|
25
|
+
}
|
|
21
26
|
if (p.includes('*') || p.includes('?')) {
|
|
22
|
-
const
|
|
23
|
-
|
|
27
|
+
const cwd = isRelative ? basePath : process.cwd();
|
|
28
|
+
const matches = globSync(p, { cwd });
|
|
29
|
+
result.push(...matches.map((m) => resolve(cwd, m)));
|
|
24
30
|
}
|
|
25
31
|
else {
|
|
26
|
-
result.push(p);
|
|
32
|
+
result.push(isRelative ? resolve(basePath, p) : p);
|
|
27
33
|
}
|
|
28
34
|
}
|
|
29
|
-
// Deduplicate (multiple globs could match the same file)
|
|
30
35
|
return [...new Set(result)];
|
|
31
36
|
}
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
if (!Array.isArray(rawPaths) || rawPaths.length === 0) {
|
|
35
|
-
throw new SloopError("No files provided", "Please provide at least one file path or glob pattern to analyze.", false);
|
|
36
|
-
}
|
|
37
|
-
// Expand any glob patterns (e.g. "src/**/*.ts") into concrete file paths
|
|
38
|
-
const filePaths = expandGlobs(rawPaths);
|
|
37
|
+
function resolveAndValidatePaths(rawPaths, basePath) {
|
|
38
|
+
const filePaths = expandGlobs(rawPaths, basePath);
|
|
39
39
|
if (filePaths.length === 0) {
|
|
40
|
-
throw new SloopError(
|
|
40
|
+
throw new SloopError('No files matched', 'No files matched the provided patterns:\n' + rawPaths.map((p) => `- ${p}`).join('\n'), false);
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
const missingFiles = filePaths.filter(fp => !existsSync(fp));
|
|
42
|
+
const missingFiles = filePaths.filter((fp) => !existsSync(fp));
|
|
44
43
|
if (missingFiles.length > 0) {
|
|
45
|
-
throw new SloopError(`Files not found: ${missingFiles.join(', ')}`,
|
|
44
|
+
throw new SloopError(`Files not found: ${missingFiles.join(', ')}`, 'The following files do not exist:\n' + missingFiles.map((f) => `- ${f}`).join('\n'), false);
|
|
46
45
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// Group files by project root for scope management
|
|
51
|
-
// Pass all files to getOrCreateScope so they're pre-registered for listFiles
|
|
46
|
+
return filePaths;
|
|
47
|
+
}
|
|
48
|
+
async function groupByScope(filePaths) {
|
|
52
49
|
const filesByScope = new Map();
|
|
53
50
|
for (const filePath of filePaths) {
|
|
54
51
|
const scopeId = await getOrCreateScope(filePath, filePaths);
|
|
@@ -57,79 +54,57 @@ export async function handleAnalyzeFiles(args) {
|
|
|
57
54
|
}
|
|
58
55
|
filesByScope.get(scopeId).push(filePath);
|
|
59
56
|
}
|
|
60
|
-
|
|
57
|
+
return filesByScope;
|
|
58
|
+
}
|
|
59
|
+
function buildSummary(allResults) {
|
|
60
|
+
const bySeverity = { blocker: 0, critical: 0, major: 0, minor: 0, info: 0 };
|
|
61
|
+
for (const result of allResults) {
|
|
62
|
+
for (const issue of result.issues) {
|
|
63
|
+
const key = issue.severity.toLowerCase();
|
|
64
|
+
if (key in bySeverity)
|
|
65
|
+
bySeverity[key]++;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
totalFiles: allResults.length,
|
|
70
|
+
totalIssues: allResults.reduce((sum, r) => sum + r.issueCount, 0),
|
|
71
|
+
filesWithIssues: allResults.filter((r) => r.issueCount > 0).length,
|
|
72
|
+
bySeverity,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export async function handleAnalyzeFiles(args) {
|
|
76
|
+
const { filePaths: rawPaths, basePath, minSeverity, excludeRules, } = args;
|
|
77
|
+
if (!Array.isArray(rawPaths) || rawPaths.length === 0) {
|
|
78
|
+
throw new SloopError('No files provided', 'Please provide at least one file path or glob pattern to analyze.', false);
|
|
79
|
+
}
|
|
80
|
+
const filePaths = resolveAndValidatePaths(rawPaths, basePath);
|
|
81
|
+
console.error(`[MCP] Batch analyzing ${filePaths.length} files...`);
|
|
82
|
+
const bridge = await ensureSloopBridge(filePaths[0]);
|
|
83
|
+
const filesByScope = await groupByScope(filePaths);
|
|
61
84
|
const allResults = [];
|
|
62
85
|
for (const [scopeId, scopeFiles] of filesByScope) {
|
|
63
86
|
console.error(`[MCP] Analyzing ${scopeFiles.length} files in scope ${scopeId}`);
|
|
64
87
|
const rawResult = await bridge.analyzeFilesAndTrack(scopeId, scopeFiles);
|
|
65
|
-
const rawIssues = rawResult.raisedIssues?.length ? rawResult.raisedIssues :
|
|
66
|
-
// Group issues by file
|
|
88
|
+
const rawIssues = rawResult.raisedIssues?.length ? rawResult.raisedIssues : rawResult.rawIssues || [];
|
|
67
89
|
const issuesByFile = new Map();
|
|
68
90
|
for (const issue of rawIssues) {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
issuesByFile.get(fileUri).push(issue);
|
|
91
|
+
const arr = issuesByFile.get(issue.fileUri) || [];
|
|
92
|
+
arr.push(issue);
|
|
93
|
+
issuesByFile.set(issue.fileUri, arr);
|
|
74
94
|
}
|
|
75
|
-
// Create results for each file
|
|
76
95
|
for (const filePath of scopeFiles) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const minLevel = severityOrder[minSeverity];
|
|
84
|
-
transformedIssues = transformedIssues.filter(issue => (severityOrder[issue.severity] || 0) >= minLevel);
|
|
85
|
-
}
|
|
86
|
-
if (excludeRules && excludeRules.length > 0) {
|
|
87
|
-
transformedIssues = transformedIssues.filter(issue => !excludeRules.includes(issue.rule));
|
|
88
|
-
}
|
|
89
|
-
allResults.push({
|
|
90
|
-
filePath,
|
|
91
|
-
language: detectLanguage(filePath),
|
|
92
|
-
issueCount: transformedIssues.length,
|
|
93
|
-
issues: transformedIssues,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// Calculate overall summary
|
|
98
|
-
const overallSummary = {
|
|
99
|
-
totalFiles: allResults.length,
|
|
100
|
-
totalIssues: allResults.reduce((sum, r) => sum + r.issueCount, 0),
|
|
101
|
-
filesWithIssues: allResults.filter(r => r.issueCount > 0).length,
|
|
102
|
-
bySeverity: {
|
|
103
|
-
blocker: 0,
|
|
104
|
-
critical: 0,
|
|
105
|
-
major: 0,
|
|
106
|
-
minor: 0,
|
|
107
|
-
info: 0,
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
for (const result of allResults) {
|
|
111
|
-
for (const issue of result.issues) {
|
|
112
|
-
const severity = issue.severity.toLowerCase();
|
|
113
|
-
if (severity in overallSummary.bySeverity) {
|
|
114
|
-
overallSummary.bySeverity[severity]++;
|
|
115
|
-
}
|
|
96
|
+
let issues = transformSloopIssues(issuesByFile.get(`file://${filePath}`) || []);
|
|
97
|
+
if (minSeverity)
|
|
98
|
+
issues = filterBySeverity(issues, minSeverity);
|
|
99
|
+
if (excludeRules?.length)
|
|
100
|
+
issues = issues.filter((i) => !excludeRules.includes(i.rule));
|
|
101
|
+
allResults.push({ filePath, language: detectLanguage(filePath), issueCount: issues.length, issues });
|
|
116
102
|
}
|
|
117
103
|
}
|
|
118
|
-
const batchResult = {
|
|
119
|
-
|
|
120
|
-
summary: overallSummary,
|
|
121
|
-
};
|
|
122
|
-
// Store in batch results for MCP resources
|
|
123
|
-
const batchId = `batch-${Date.now()}`;
|
|
124
|
-
batchResults.set(batchId, batchResult);
|
|
125
|
-
const formattedResult = formatBatchAnalysisResult(batchResult);
|
|
104
|
+
const batchResult = { files: allResults, summary: buildSummary(allResults) };
|
|
105
|
+
batchResults.set(`batch-${Date.now()}`, batchResult);
|
|
126
106
|
return {
|
|
127
|
-
content: [
|
|
128
|
-
{
|
|
129
|
-
type: "text",
|
|
130
|
-
text: formattedResult,
|
|
131
|
-
},
|
|
132
|
-
],
|
|
107
|
+
content: [{ type: 'text', text: formatBatchAnalysisResult(batchResult) }],
|
|
133
108
|
};
|
|
134
109
|
}
|
|
135
110
|
//# sourceMappingURL=analyze-files.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-files.js","sourceRoot":"","sources":["../../src/tools/analyze-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,0EAA0E;AAC1E,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAA4E,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C;;;GAGG;AACH,SAAS,WAAW,CAAC,KAAe;
|
|
1
|
+
{"version":3,"file":"analyze-files.js","sourceRoot":"","sources":["../../src/tools/analyze-files.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-all-quick-fixes.d.ts","sourceRoot":"","sources":["../../src/tools/apply-all-quick-fixes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apply-all-quick-fixes.d.ts","sourceRoot":"","sources":["../../src/tools/apply-all-quick-fixes.ts"],"names":[],"mappings":"AAmFA,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,GAAG;;;;;GA8CvD"}
|
|
@@ -1,164 +1,94 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from
|
|
2
|
-
import { SloopError } from
|
|
3
|
-
import { ensureSloopBridge } from
|
|
4
|
-
import { getOrCreateScope } from
|
|
5
|
-
import { notifyFileSystemChanged } from
|
|
6
|
-
import { transformSloopIssues } from
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { SloopError } from '../errors.js';
|
|
3
|
+
import { ensureSloopBridge } from '../utils/sloop.js';
|
|
4
|
+
import { getOrCreateScope } from '../utils/scope.js';
|
|
5
|
+
import { notifyFileSystemChanged } from '../utils/filesystem.js';
|
|
6
|
+
import { transformSloopIssues } from '../utils/transforms.js';
|
|
7
|
+
import { applyTextEdits } from '../utils/quick-fix.js';
|
|
8
|
+
function applyFixesToFile(filePath, issues) {
|
|
9
|
+
const applied = [];
|
|
10
|
+
const failed = [];
|
|
11
|
+
// Sort descending by line to avoid line number shifts
|
|
12
|
+
const sorted = [...issues].sort((a, b) => {
|
|
13
|
+
return (b.textRange?.startLine || b.startLine || 0) - (a.textRange?.startLine || a.startLine || 0);
|
|
14
|
+
});
|
|
15
|
+
for (const issue of sorted) {
|
|
16
|
+
const line = issue.textRange?.startLine || issue.startLine || 0;
|
|
17
|
+
const rule = issue.ruleKey;
|
|
18
|
+
const quickFix = issue.quickFixes[0];
|
|
19
|
+
try {
|
|
20
|
+
const lines = readFileSync(filePath, 'utf-8').split('\n');
|
|
21
|
+
applyTextEdits(lines, quickFix);
|
|
22
|
+
writeFileSync(filePath, lines.join('\n'), 'utf-8');
|
|
23
|
+
applied.push({ line, rule, message: quickFix.message || 'Applied automated fix' });
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
failed.push({ line, rule, error: error instanceof Error ? error.message : String(error) });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return { applied, failed };
|
|
30
|
+
}
|
|
31
|
+
function formatFixList(label, items) {
|
|
32
|
+
if (items.length === 0)
|
|
33
|
+
return '';
|
|
34
|
+
const lines = items.map((i) => `- Line ${i.line}: ${i.rule} - ${i.message || i.error}`);
|
|
35
|
+
return `**${label}:**\n${lines.join('\n')}\n\n`;
|
|
36
|
+
}
|
|
37
|
+
function formatRemainingIssues(remaining) {
|
|
38
|
+
if (remaining.length === 0)
|
|
39
|
+
return `🎉 All issues resolved! The file has no remaining code quality issues.\n`;
|
|
40
|
+
let out = `**Remaining Issues (require manual fixing):**\n`;
|
|
41
|
+
for (const severity of ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO']) {
|
|
42
|
+
const issues = remaining.filter((i) => i.severity === severity);
|
|
43
|
+
if (issues.length === 0)
|
|
44
|
+
continue;
|
|
45
|
+
out += `\n${severity} (${issues.length}):\n`;
|
|
46
|
+
for (const issue of issues)
|
|
47
|
+
out += `- Line ${issue.line}: ${issue.rule} - ${issue.message}\n`;
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
function formatSummary(filePath, applied, failed, remaining) {
|
|
52
|
+
let summary = `✅ **Quick fixes applied**\n\nFile: ${filePath}\nApplied: ${applied.length} fixes\n`;
|
|
53
|
+
if (failed.length > 0)
|
|
54
|
+
summary += `Failed: ${failed.length} fixes\n`;
|
|
55
|
+
summary += `Remaining issues: ${remaining.length}\n\n`;
|
|
56
|
+
summary += formatFixList('Fixed Issues', applied);
|
|
57
|
+
summary += formatFixList('Failed Fixes', failed);
|
|
58
|
+
summary += formatRemainingIssues(remaining);
|
|
59
|
+
return summary;
|
|
60
|
+
}
|
|
7
61
|
export async function handleApplyAllQuickFixes(args) {
|
|
8
62
|
const { filePath } = args;
|
|
9
|
-
console.error(`[MCP] Applying all quick fixes for ${filePath}`);
|
|
10
|
-
// Validate file exists
|
|
11
63
|
if (!existsSync(filePath)) {
|
|
12
64
|
throw new SloopError(`File not found: ${filePath}`, `The file ${filePath} does not exist. Please check the path and try again.`, false);
|
|
13
65
|
}
|
|
14
|
-
|
|
15
|
-
const bridge = await ensureSloopBridge();
|
|
66
|
+
const bridge = await ensureSloopBridge(filePath);
|
|
16
67
|
const scopeId = await getOrCreateScope(filePath);
|
|
17
68
|
const rawResult = await bridge.analyzeFilesAndTrack(scopeId, [filePath]);
|
|
18
|
-
const rawIssues = rawResult.raisedIssues?.length ? rawResult.raisedIssues :
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const issuesWithQuickFixes = rawIssues.filter((issue) => {
|
|
22
|
-
const hasQuickFixes = issue.quickFixes && issue.quickFixes.length > 0;
|
|
23
|
-
if (hasQuickFixes) {
|
|
24
|
-
console.error(`[DEBUG] Issue at line ${issue.textRange?.startLine || issue.startLine}: ${issue.ruleKey} has ${issue.quickFixes.length} quick fixes`);
|
|
25
|
-
}
|
|
26
|
-
return hasQuickFixes;
|
|
27
|
-
});
|
|
28
|
-
console.error(`[MCP] Found ${issuesWithQuickFixes.length} issues with quick fixes`);
|
|
29
|
-
if (issuesWithQuickFixes.length === 0) {
|
|
69
|
+
const rawIssues = rawResult.raisedIssues?.length ? rawResult.raisedIssues : rawResult.rawIssues || [];
|
|
70
|
+
const fixableIssues = rawIssues.filter((issue) => issue.quickFixes?.length > 0);
|
|
71
|
+
if (fixableIssues.length === 0) {
|
|
30
72
|
return {
|
|
31
73
|
content: [
|
|
32
74
|
{
|
|
33
|
-
type:
|
|
75
|
+
type: 'text',
|
|
34
76
|
text: `ℹ️ **No quick fixes available**\n\nFile: ${filePath}\nTotal issues: ${rawIssues.length}\n\nNone of the issues in this file have automated quick fixes available. All issues must be fixed manually.`,
|
|
35
77
|
},
|
|
36
78
|
],
|
|
37
79
|
};
|
|
38
80
|
}
|
|
39
|
-
|
|
40
|
-
const sortedIssues = [...issuesWithQuickFixes].sort((a, b) => {
|
|
41
|
-
const aLine = a.textRange?.startLine || a.startLine || 0;
|
|
42
|
-
const bLine = b.textRange?.startLine || b.startLine || 0;
|
|
43
|
-
return bLine - aLine; // Descending order
|
|
44
|
-
});
|
|
45
|
-
// Apply each quick fix
|
|
46
|
-
const appliedFixes = [];
|
|
47
|
-
const failedFixes = [];
|
|
48
|
-
for (const issue of sortedIssues) {
|
|
49
|
-
const line = issue.textRange?.startLine || issue.startLine || 0;
|
|
50
|
-
const rule = issue.ruleKey;
|
|
51
|
-
const quickFix = issue.quickFixes[0]; // Use first available quick fix
|
|
52
|
-
console.error(`[MCP] Applying fix for ${rule} at line ${line}`);
|
|
53
|
-
try {
|
|
54
|
-
// Read current file content
|
|
55
|
-
let fileContent = readFileSync(filePath, 'utf-8');
|
|
56
|
-
const lines = fileContent.split('\n');
|
|
57
|
-
// Apply the quick fix edits
|
|
58
|
-
const fileEdits = quickFix.inputFileEdits || quickFix.fileEdits || [];
|
|
59
|
-
if (fileEdits.length > 0) {
|
|
60
|
-
for (const fileEdit of fileEdits) {
|
|
61
|
-
if (fileEdit.textEdits) {
|
|
62
|
-
// Sort edits in reverse order to maintain line numbers
|
|
63
|
-
const sortedEdits = [...fileEdit.textEdits].sort((a, b) => {
|
|
64
|
-
const aStart = a.range?.startLine || 0;
|
|
65
|
-
const bStart = b.range?.startLine || 0;
|
|
66
|
-
return bStart - aStart;
|
|
67
|
-
});
|
|
68
|
-
for (const edit of sortedEdits) {
|
|
69
|
-
const startLine = (edit.range?.startLine || 1) - 1;
|
|
70
|
-
const startCol = edit.range?.startLineOffset || 0;
|
|
71
|
-
const endLine = (edit.range?.endLine || startLine + 1) - 1;
|
|
72
|
-
const endCol = edit.range?.endLineOffset || lines[endLine]?.length || 0;
|
|
73
|
-
const newText = edit.newText || '';
|
|
74
|
-
if (startLine === endLine) {
|
|
75
|
-
const currentLine = lines[startLine];
|
|
76
|
-
lines[startLine] = currentLine.substring(0, startCol) + newText + currentLine.substring(endCol);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
const firstLine = lines[startLine].substring(0, startCol) + newText;
|
|
80
|
-
const lastLine = lines[endLine].substring(endCol);
|
|
81
|
-
lines.splice(startLine, endLine - startLine + 1, firstLine + lastLine);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
// Write back to file
|
|
88
|
-
fileContent = lines.join('\n');
|
|
89
|
-
writeFileSync(filePath, fileContent, 'utf-8');
|
|
90
|
-
appliedFixes.push({
|
|
91
|
-
line,
|
|
92
|
-
rule,
|
|
93
|
-
message: quickFix.message || 'Applied automated fix',
|
|
94
|
-
});
|
|
95
|
-
console.error(`[MCP] Successfully applied fix for ${rule} at line ${line}`);
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
console.error(`[MCP] Failed to apply fix for ${rule} at line ${line}:`, error);
|
|
99
|
-
failedFixes.push({
|
|
100
|
-
line,
|
|
101
|
-
rule,
|
|
102
|
-
error: error instanceof Error ? error.message : String(error),
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// Notify SLOOP about file changes
|
|
107
|
-
console.error(`[Cache] Sending file system update notification...`);
|
|
81
|
+
const { applied, failed } = applyFixesToFile(filePath, fixableIssues);
|
|
108
82
|
await notifyFileSystemChanged(filePath, scopeId);
|
|
109
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
110
|
-
// Re-analyze to get remaining issues
|
|
83
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
111
84
|
const finalResult = await bridge.analyzeFilesAndTrack(scopeId, [filePath]);
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
// Format summary
|
|
115
|
-
let summary = `✅ **Quick fixes applied**\n\n`;
|
|
116
|
-
summary += `File: ${filePath}\n`;
|
|
117
|
-
summary += `Applied: ${appliedFixes.length} fixes\n`;
|
|
118
|
-
if (failedFixes.length > 0) {
|
|
119
|
-
summary += `Failed: ${failedFixes.length} fixes\n`;
|
|
120
|
-
}
|
|
121
|
-
summary += `Remaining issues: ${remainingIssues.length}\n\n`;
|
|
122
|
-
if (appliedFixes.length > 0) {
|
|
123
|
-
summary += `**Fixed Issues:**\n`;
|
|
124
|
-
for (const fix of appliedFixes) {
|
|
125
|
-
summary += `- Line ${fix.line}: ${fix.rule} - ${fix.message}\n`;
|
|
126
|
-
}
|
|
127
|
-
summary += `\n`;
|
|
128
|
-
}
|
|
129
|
-
if (failedFixes.length > 0) {
|
|
130
|
-
summary += `**Failed Fixes:**\n`;
|
|
131
|
-
for (const fail of failedFixes) {
|
|
132
|
-
summary += `- Line ${fail.line}: ${fail.rule} - ${fail.error}\n`;
|
|
133
|
-
}
|
|
134
|
-
summary += `\n`;
|
|
135
|
-
}
|
|
136
|
-
if (remainingIssues.length > 0) {
|
|
137
|
-
summary += `**Remaining Issues (require manual fixing):**\n`;
|
|
138
|
-
const groupedBySeverity = transformedRemaining.reduce((acc, issue) => {
|
|
139
|
-
if (!acc[issue.severity])
|
|
140
|
-
acc[issue.severity] = [];
|
|
141
|
-
acc[issue.severity].push(issue);
|
|
142
|
-
return acc;
|
|
143
|
-
}, {});
|
|
144
|
-
for (const severity of ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO']) {
|
|
145
|
-
const issues = groupedBySeverity[severity] || [];
|
|
146
|
-
if (issues.length > 0) {
|
|
147
|
-
summary += `\n${severity} (${issues.length}):\n`;
|
|
148
|
-
for (const issue of issues) {
|
|
149
|
-
summary += `- Line ${issue.line}: ${issue.rule} - ${issue.message}\n`;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
summary += `🎉 All issues resolved! The file has no remaining code quality issues.\n`;
|
|
156
|
-
}
|
|
85
|
+
const remainingRaw = finalResult.raisedIssues?.length ? finalResult.raisedIssues : finalResult.rawIssues || [];
|
|
86
|
+
const remaining = transformSloopIssues(remainingRaw);
|
|
157
87
|
return {
|
|
158
88
|
content: [
|
|
159
89
|
{
|
|
160
|
-
type:
|
|
161
|
-
text:
|
|
90
|
+
type: 'text',
|
|
91
|
+
text: formatSummary(filePath, applied, failed, remaining),
|
|
162
92
|
},
|
|
163
93
|
],
|
|
164
94
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-all-quick-fixes.js","sourceRoot":"","sources":["../../src/tools/apply-all-quick-fixes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"apply-all-quick-fixes.js","sourceRoot":"","sources":["../../src/tools/apply-all-quick-fixes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAavD,SAAS,gBAAgB,CAAC,QAAgB,EAAE,MAAa;IACvD,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAEhC,sDAAsD;IACtD,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACvC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;IACrG,CAAC,CAAC,CAAC;IAEH,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,EAAE,SAAS,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC;QAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAErC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC1D,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAChC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,uBAAuB,EAAE,CAAC,CAAC;QACrF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,aAAa,CACpB,KAAa,EACb,KAA8E;IAE9E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IACxF,OAAO,KAAK,KAAK,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;AAClD,CAAC;AAED,SAAS,qBAAqB,CAAC,SAAkD;IAC/E,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,0EAA0E,CAAC;IAE9G,IAAI,GAAG,GAAG,iDAAiD,CAAC;IAC5D,KAAK,MAAM,QAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;QACzE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAClC,GAAG,IAAI,KAAK,QAAQ,KAAK,MAAM,CAAC,MAAM,MAAM,CAAC;QAC7C,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,GAAG,IAAI,UAAU,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,OAAO,IAAI,CAAC;IAChG,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CACpB,QAAgB,EAChB,OAAoB,EACpB,MAAoB,EACpB,SAAkD;IAElD,IAAI,OAAO,GAAG,sCAAsC,QAAQ,cAAc,OAAO,CAAC,MAAM,UAAU,CAAC;IACnG,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,WAAW,MAAM,CAAC,MAAM,UAAU,CAAC;IACrE,OAAO,IAAI,qBAAqB,SAAS,CAAC,MAAM,MAAM,CAAC;IACvD,OAAO,IAAI,aAAa,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAClD,OAAO,IAAI,aAAa,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,IAAI,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC5C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,IAAS;IACtD,MAAM,EAAE,QAAQ,EAAE,GAAG,IAA4B,CAAC;IAElD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAClB,mBAAmB,QAAQ,EAAE,EAC7B,YAAY,QAAQ,uDAAuD,EAC3E,KAAK,CACN,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC;IAEtG,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;IAErF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,4CAA4C,QAAQ,mBAAmB,SAAS,CAAC,MAAM,8GAA8G;iBAC5M;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAEtE,MAAM,uBAAuB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IAEzD,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,IAAI,EAAE,CAAC;IAC/G,MAAM,SAAS,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAErD,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC;aAC1D;SACF;KACF,CAAC;AACJ,CAAC"}
|