@nielspeter/sonarlint-mcp-server 0.3.1 → 0.4.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +14 -1
  3. package/dist/errors.d.ts.map +1 -1
  4. package/dist/errors.js +7 -1
  5. package/dist/errors.js.map +1 -1
  6. package/dist/index.js +5 -23
  7. package/dist/index.js.map +1 -1
  8. package/dist/sloop-bridge.d.ts +10 -1
  9. package/dist/sloop-bridge.d.ts.map +1 -1
  10. package/dist/sloop-bridge.js +102 -160
  11. package/dist/sloop-bridge.js.map +1 -1
  12. package/dist/state.d.ts +2 -1
  13. package/dist/state.d.ts.map +1 -1
  14. package/dist/state.js +6 -2
  15. package/dist/state.js.map +1 -1
  16. package/dist/tools/analyze-content.js +1 -1
  17. package/dist/tools/analyze-content.js.map +1 -1
  18. package/dist/tools/analyze-file.d.ts.map +1 -1
  19. package/dist/tools/analyze-file.js +4 -6
  20. package/dist/tools/analyze-file.js.map +1 -1
  21. package/dist/tools/analyze-files.d.ts.map +1 -1
  22. package/dist/tools/analyze-files.js +75 -71
  23. package/dist/tools/analyze-files.js.map +1 -1
  24. package/dist/tools/apply-all-quick-fixes.d.ts.map +1 -1
  25. package/dist/tools/apply-all-quick-fixes.js +65 -139
  26. package/dist/tools/apply-all-quick-fixes.js.map +1 -1
  27. package/dist/tools/apply-quick-fix.d.ts.map +1 -1
  28. package/dist/tools/apply-quick-fix.js +5 -76
  29. package/dist/tools/apply-quick-fix.js.map +1 -1
  30. package/dist/tools/health-check.d.ts.map +1 -1
  31. package/dist/tools/health-check.js +15 -7
  32. package/dist/tools/health-check.js.map +1 -1
  33. package/dist/tools/list-active-rules.d.ts.map +1 -1
  34. package/dist/tools/list-active-rules.js +3 -2
  35. package/dist/tools/list-active-rules.js.map +1 -1
  36. package/dist/utils/file-registration.js +1 -1
  37. package/dist/utils/file-registration.js.map +1 -1
  38. package/dist/utils/formatting.d.ts.map +1 -1
  39. package/dist/utils/quick-fix.d.ts +14 -0
  40. package/dist/utils/quick-fix.d.ts.map +1 -0
  41. package/dist/utils/quick-fix.js +44 -0
  42. package/dist/utils/quick-fix.js.map +1 -0
  43. package/dist/utils/scope.d.ts +24 -3
  44. package/dist/utils/scope.d.ts.map +1 -1
  45. package/dist/utils/scope.js +46 -7
  46. package/dist/utils/scope.js.map +1 -1
  47. package/dist/utils/sloop.d.ts.map +1 -1
  48. package/dist/utils/sloop.js +5 -1
  49. package/dist/utils/sloop.js.map +1 -1
  50. package/package.json +1 -1
  51. package/dist/tools/analyze-project.d.ts +0 -7
  52. package/dist/tools/analyze-project.d.ts.map +0 -1
  53. package/dist/tools/analyze-project.js +0 -109
  54. package/dist/tools/analyze-project.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.4.1](https://github.com/nielspeter/sonarlint-mcp-server/compare/v0.4.0...v0.4.1) (2026-03-30)
6
+
7
+
8
+ ### Features
9
+
10
+ * add basePath parameter for relative paths and globs in check_files ([3fbc1ff](https://github.com/nielspeter/sonarlint-mcp-server/commit/3fbc1ff2737c12b174818bc9ba31cd38c79ba695))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * resolve 15 sonarlint issues across codebase ([be91de6](https://github.com/nielspeter/sonarlint-mcp-server/commit/be91de6d3da6b7c38e2a7720e5285f57137f3d81))
16
+
17
+
18
+ ### Code Refactoring
19
+
20
+ * reduce cognitive complexity to zero sonarlint issues ([213aad6](https://github.com/nielspeter/sonarlint-mcp-server/commit/213aad634427b302c31d23ab2f9dbaa7ebe1f138))
21
+
22
+ ## [0.4.0](https://github.com/nielspeter/sonarlint-mcp-server/compare/v0.3.1...v0.4.0) (2026-03-30)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * resolve SLOOP analysis hang by pre-registering files before scope creation ([ee1bfb2](https://github.com/nielspeter/sonarlint-mcp-server/commit/ee1bfb24be94b72838fc1fb4e4ff17ba297a9d19))
28
+
5
29
  ### [0.3.1](https://github.com/nielspeter/sonarlint-mcp-server/compare/v0.3.0...v0.3.1) (2026-03-30)
6
30
 
7
31
 
package/README.md CHANGED
@@ -97,7 +97,6 @@ function process(data) {
97
97
  |------|-------------|
98
98
  | `check_quality` | Check a file for code quality issues |
99
99
  | `check_files` | Check multiple files in one call |
100
- | `check_project` | Run a full project-wide quality scan |
101
100
  | `check_code` | Check a code snippet (no file on disk needed) |
102
101
  | `fix_issue` | Automatically fix one specific issue |
103
102
  | `fix_all_issues` | Automatically fix all fixable issues in a file |
@@ -158,6 +157,20 @@ The server uses SonarLint's standalone SLOOP backend with:
158
157
  - **Bi-directional RPC:** Client request handlers implemented
159
158
  - **Session Storage:** Results stored in memory for multi-turn conversations
160
159
 
160
+ ### SLOOP Integration: Scope Lifecycle
161
+
162
+ SLOOP requires a specific initialization sequence. Getting this wrong causes analysis to hang:
163
+
164
+ 1. **Pre-register files** — Store file DTOs in `scopeFiles` map before creating the scope. SLOOP calls `listFiles` synchronously during scope creation, so files must already be available.
165
+ 2. **Create scope** — Send `addConfigurationScope` notification to SLOOP.
166
+ 3. **Wait for readiness** — SLOOP sends `didChangeAnalysisReadiness` when the scope is ready. Analysis requests before this point will fail silently.
167
+ 4. **Analyse** — Call `analyzeFilesAndTrack` with the files.
168
+
169
+ Key design decisions:
170
+ - **No directory scanning in `listFiles`** — Only return the specific files requested for analysis. Scanning the project root returned 500+ files on real projects and caused multi-minute hangs.
171
+ - **`getBaseDir` returns project root** — Detected via `package.json`, `.git`, etc. SLOOP uses this for `.gitignore` matching and file exclusion patterns.
172
+ - **`ideRelativePath` relative to project root** — SLOOP's `WildcardPattern.match` requires this; null values cause NPEs.
173
+
161
174
  ## Development
162
175
 
163
176
  ```bash
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;IAG1B,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,OAAO;gBAF3B,OAAO,EAAE,MAAM,EACR,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,OAAe;CAKtC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO;;;;;;EA0B7C"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;IAG1B,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,OAAO;gBAF3B,OAAO,EAAE,MAAM,EACR,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,OAAe;CAKtC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO;;;;;;EA6B7C"}
package/dist/errors.js CHANGED
@@ -30,7 +30,13 @@ export function handleToolError(error) {
30
30
  isError: true,
31
31
  };
32
32
  }
33
- const errorMessage = error instanceof Error ? error.message : String(error);
33
+ let errorMessage;
34
+ if (error instanceof Error)
35
+ errorMessage = error.message;
36
+ else if (typeof error === 'string')
37
+ errorMessage = error;
38
+ else
39
+ errorMessage = JSON.stringify(error);
34
40
  return {
35
41
  content: [
36
42
  {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IAG1B;IACA;IAHT,YACE,OAAe,EACR,WAAmB,EACnB,cAAuB,KAAK;QAEnC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,gBAAW,GAAX,WAAW,CAAQ;QACnB,gBAAW,GAAX,WAAW,CAAiB;QAGnC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;IAExD,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,gBAAgB,KAAK,CAAC,WAAW,EAAE;iBAC1C;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE5E,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,gBAAgB,YAAY,EAAE;aACrC;SACF;QACD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IAG1B;IACA;IAHT,YACE,OAAe,EACR,WAAmB,EACnB,cAAuB,KAAK;QAEnC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,gBAAW,GAAX,WAAW,CAAQ;QACnB,gBAAW,GAAX,WAAW,CAAiB;QAGnC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;IAExD,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,gBAAgB,KAAK,CAAC,WAAW,EAAE;iBAC1C;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,IAAI,YAAoB,CAAC;IACzB,IAAI,KAAK,YAAY,KAAK;QAAE,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;SACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,YAAY,GAAG,KAAK,CAAC;;QACpD,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAE1C,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,gBAAgB,YAAY,EAAE;aACrC;SACF;QACD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
package/dist/index.js CHANGED
@@ -11,7 +11,6 @@ import { handleAnalyzeFiles } from "./tools/analyze-files.js";
11
11
  import { handleAnalyzeContent } from "./tools/analyze-content.js";
12
12
  import { handleListActiveRules } from "./tools/list-active-rules.js";
13
13
  import { handleHealthCheck } from "./tools/health-check.js";
14
- import { handleAnalyzeProject } from "./tools/analyze-project.js";
15
14
  import { handleApplyQuickFix } from "./tools/apply-quick-fix.js";
16
15
  import { handleApplyAllQuickFixes } from "./tools/apply-all-quick-fixes.js";
17
16
  import { getSloopBridge } from "./state.js";
@@ -28,7 +27,7 @@ const server = new McpServer({
28
27
  });
29
28
  // Register tool: check_quality
30
29
  server.registerTool('check_quality', {
31
- description: "Check a file for code quality issues — bugs, code smells, security vulnerabilities, and complexity problems. Like having SonarLint in your IDE. Use after writing or modifying code to catch issues early. Returns issues with exact line numbers, severity, and available quick fixes. For multiple files use check_files; for whole projects use check_project.",
30
+ description: "Check a file for code quality issues — bugs, code smells, security vulnerabilities, and complexity problems. Like having SonarLint in your IDE. Use after writing or modifying code to catch issues early. Returns issues with exact line numbers, severity, and available quick fixes. For multiple files use check_files.",
32
31
  inputSchema: {
33
32
  filePath: z.string().describe("Absolute path to the file to analyze (e.g., /path/to/file.js)"),
34
33
  minSeverity: z.enum(["INFO", "MINOR", "MAJOR", "CRITICAL", "BLOCKER"]).optional().describe("Minimum severity level to include. Filters out issues below this level. Default: INFO (show all)"),
@@ -44,9 +43,10 @@ server.registerTool('check_quality', {
44
43
  });
45
44
  // Register tool: check_files
46
45
  server.registerTool('check_files', {
47
- description: "Check multiple files for code quality issues in one call — bugs, code smells, security vulnerabilities. Use when reviewing or modifying several files. Output is compact: only files with issues are shown, clean files get a summary count. For a single file use check_quality; for whole projects use check_project.",
46
+ description: "Check multiple files for code quality issues in one call — bugs, code smells, security vulnerabilities. Use when reviewing or modifying several files. Supports glob patterns (e.g. 'src/**/*.ts'). When using relative paths or globs, provide basePath so they resolve correctly. Output is compact: only files with issues are shown, clean files get a summary count. For a single file use check_quality.",
48
47
  inputSchema: {
49
- filePaths: stringArray.describe("Array of absolute file paths to analyze"),
48
+ filePaths: stringArray.describe("Array of file paths or glob patterns to analyze (e.g., ['/path/to/file.ts', 'src/**/*.js'])"),
49
+ basePath: z.string().optional().describe("Project root directory for resolving relative paths and globs (e.g., '/Users/me/project'). Required when filePaths contains relative paths."),
50
50
  groupByFile: z.boolean().optional().default(true).describe("Group issues by file in output (default: true)"),
51
51
  minSeverity: z.enum(["INFO", "MINOR", "MAJOR", "CRITICAL", "BLOCKER"]).optional().describe("Minimum severity level to include. Filters out issues below this level. Default: INFO (show all)"),
52
52
  excludeRules: stringArray.optional().describe("List of rule IDs to exclude (e.g., ['typescript:S1135', 'javascript:S125'])"),
@@ -101,24 +101,6 @@ server.registerTool('health_check', {
101
101
  return handleToolError(error);
102
102
  }
103
103
  });
104
- // Register tool: check_project
105
- server.registerTool('check_project', {
106
- description: "Run a full code quality scan on a project directory — finds bugs, code smells, security vulnerabilities, and complexity issues across all source files. Use for project-wide quality assessment or before a release. Output is compact: only files with issues are shown, clean files get a summary count.",
107
- inputSchema: {
108
- projectPath: z.string().describe("Absolute path to the project directory to scan"),
109
- maxFiles: z.number().optional().default(100).describe("Maximum number of files to analyze (default: 100, prevents overwhelming output)"),
110
- minSeverity: z.enum(["INFO", "MINOR", "MAJOR", "CRITICAL", "BLOCKER"]).optional().describe("Minimum severity level to include. Filters out issues below this level. Default: INFO (show all)"),
111
- excludeRules: stringArray.optional().describe("List of rule IDs to exclude (e.g., ['typescript:S1135', 'javascript:S125'])"),
112
- includePatterns: stringArray.optional().describe("File glob patterns to include (e.g., ['src/**/*.ts', 'lib/**/*.js']). Default: all supported extensions"),
113
- },
114
- }, async (args) => {
115
- try {
116
- return await handleAnalyzeProject(args);
117
- }
118
- catch (error) {
119
- return handleToolError(error);
120
- }
121
- });
122
104
  // Register tool: fix_issue
123
105
  server.registerTool('fix_issue', {
124
106
  description: "Automatically fix one specific code quality issue. Applies the SonarLint-suggested fix for the issue at the given file, line, and rule. The file is modified directly. To fix all issues in a file at once, use fix_all_issues instead.",
@@ -173,7 +155,7 @@ async function main() {
173
155
  console.error("[MCP] Starting SonarLint MCP Server...");
174
156
  console.error(`[MCP] Version: ${packageJson.version}`);
175
157
  console.error("[MCP] Mode: Standalone (no IDE required)");
176
- console.error("[MCP] Tools: check_quality, check_files, check_code, check_project, list_rules, fix_issue, fix_all_issues, health_check");
158
+ console.error("[MCP] Tools: check_quality, check_files, check_code, list_rules, fix_issue, fix_all_issues, health_check");
177
159
  console.error("[MCP] Features:");
178
160
  console.error("[MCP] - Session storage for multi-turn conversations");
179
161
  console.error("[MCP] - Batch analysis for multiple files");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,oEAAoE;AACpE,MAAM,WAAW,GAAG,CAAC,CAAC,UAAU,CAC9B,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EACxD,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CACpB,CAAC;AACF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAE7F,4BAA4B;AAC5B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,sBAAsB;IAC5B,OAAO,EAAE,WAAW,CAAC,OAAO;CAC7B,CAAC,CAAC;AAEH,+BAA+B;AAC/B,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;IACE,WAAW,EAAE,6TAA6T;IAC1U,WAAW,EAAE;QACX,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+DAA+D,CAAC;QAC9F,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kGAAkG,CAAC;QAC9L,YAAY,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6EAA6E,CAAC;KAC7H;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,IAAI,CAAC;QACH,OAAO,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC,CACF,CAAC;AAEF,6BAA6B;AAC7B,MAAM,CAAC,YAAY,CACjB,aAAa,EACb;IACE,WAAW,EAAE,gZAAgZ;IAC7Z,WAAW,EAAE;QACX,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,6FAA6F,CAAC;QAC9H,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6IAA6I,CAAC;QACvL,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,gDAAgD,CAAC;QAC5G,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kGAAkG,CAAC;QAC9L,YAAY,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6EAA6E,CAAC;KAC7H;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,IAAI,CAAC;QACH,OAAO,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC,CACF,CAAC;AAEF,4BAA4B;AAC5B,MAAM,CAAC,YAAY,CACjB,YAAY,EACZ;IACE,WAAW,EAAE,gRAAgR;IAC7R,WAAW,EAAE;QACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QAC3D,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,qCAAqC,CAAC;QACrI,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yDAAyD,CAAC;KACpG;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,IAAI,CAAC;QACH,OAAO,MAAM,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC,CACF,CAAC;AAEF,4BAA4B;AAC5B,MAAM,CAAC,YAAY,CACjB,YAAY,EACZ;IACE,WAAW,EAAE,iSAAiS;IAC9S,WAAW,EAAE;QACX,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;KACjJ;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,IAAI,CAAC;QACH,OAAO,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC,CACF,CAAC;AAEF,6DAA6D;AAC7D,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;IACE,WAAW,EAAE,8LAA8L;IAC3M,WAAW,EAAE,EAAE;CAChB,EACD,KAAK,IAAI,EAAE;IACT,IAAI,CAAC;QACH,OAAO,MAAM,iBAAiB,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC,CACF,CAAC;AAEF,2BAA2B;AAC3B,MAAM,CAAC,YAAY,CACjB,WAAW,EACX;IACE,WAAW,EAAE,yOAAyO;IACtP,WAAW,EAAE;QACX,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QACjE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QACrD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;KAChE;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,IAAI,CAAC;QACH,OAAO,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC,CACF,CAAC;AAEF,gCAAgC;AAChC,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;IACE,WAAW,EAAE,mPAAmP;IAChQ,WAAW,EAAE;QACX,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;KAClE;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,IAAI,CAAC;QACH,OAAO,MAAM,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC,CACF,CAAC;AAEF,yBAAyB;AACzB,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE1B,oBAAoB;AACpB,KAAK,UAAU,QAAQ;IACrB,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,UAAU,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAEhC,mBAAmB;AACnB,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;IACxD,OAAO,CAAC,KAAK,CAAC,kBAAkB,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC1D,OAAO,CAAC,KAAK,CAAC,0GAA0G,CAAC,CAAC;IAC1H,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACjC,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;IACxE,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC7D,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC5D,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAChE,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAE/C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;AACjE,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -22,7 +22,11 @@ export declare class SloopBridge extends EventEmitter {
22
22
  private setupMessageHandlers;
23
23
  private processMessages;
24
24
  private handleMessage;
25
- private findFilesInDirectory;
25
+ private handleResponse;
26
+ private handleNotification;
27
+ private onRaiseIssues;
28
+ private onRaiseHotspots;
29
+ private onAnalysisReadiness;
26
30
  private handleClientRequest;
27
31
  private sendResponse;
28
32
  sendRequest(method: string, params?: any): Promise<any>;
@@ -37,6 +41,11 @@ export declare class SloopBridge extends EventEmitter {
37
41
  * Returns a map of rule key -> rule definition.
38
42
  */
39
43
  listAllStandaloneRulesDefinitions(): Promise<any>;
44
+ /**
45
+ * Wait for a scope to become ready for analysis.
46
+ * SLOOP emits didChangeAnalysisReadiness after processing addConfigurationScope.
47
+ */
48
+ waitForScopeReady(scopeId: string, timeoutMs?: number): Promise<void>;
40
49
  addConfigurationScope(scopeId: string, params?: {
41
50
  name?: string;
42
51
  parentId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"sloop-bridge.d.ts","sourceRoot":"","sources":["../src/sloop-bridge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAOtC,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAI3B;IACL,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsF;IAC7G,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwB;gBAE3C,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,GAAE,WAAgB;IAwB1D,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,gBAAgB;IAUlB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAwE9B,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,aAAa;IAyDrB,OAAO,CAAC,oBAAoB;IAiC5B,OAAO,CAAC,mBAAmB;IA0H3B,OAAO,CAAC,YAAY;IAgBd,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAyC7D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,IAAI;IAuBpD,OAAO,CAAC,cAAc;YAeR,UAAU;IAoFxB,OAAO,CAAC,gBAAgB;IAQxB,WAAW,IAAI,OAAO;IAIhB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;;OAGG;IACG,iCAAiC,IAAI,OAAO,CAAC,GAAG,CAAC;IAIvD,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;IAYzF,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;CAsDrF"}
1
+ {"version":3,"file":"sloop-bridge.d.ts","sourceRoot":"","sources":["../src/sloop-bridge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAQtC,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAI3B;IACL,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsF;IAC7G,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwB;gBAE3C,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,GAAE,WAAgB;IAwB1D,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,gBAAgB;IAUlB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAwE9B,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,mBAAmB;IAqD3B,OAAO,CAAC,YAAY;IAgBd,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAyC7D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,IAAI;IAuBpD,OAAO,CAAC,cAAc;YAeR,UAAU;IAoFxB,OAAO,CAAC,gBAAgB;IAQxB,WAAW,IAAI,OAAO;IAIhB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;;OAGG;IACG,iCAAiC,IAAI,OAAO,CAAC,GAAG,CAAC;IAIvD;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,SAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBpE,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;IAYzF,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;CA4DrF"}
@@ -1,10 +1,11 @@
1
1
  import { spawn } from 'child_process';
2
2
  import { EventEmitter } from 'events';
3
3
  import { tmpdir } from 'os';
4
- import { join, relative } from 'path';
5
- import { existsSync, mkdirSync, readdirSync, statSync, readFileSync } from 'fs';
4
+ import { join } from 'path';
5
+ import { existsSync, mkdirSync, readdirSync } from 'fs';
6
6
  import { IssueCollector } from './utils/issue-collector.js';
7
7
  import { buildClientFileDtos } from './utils/file-registration.js';
8
+ import { scopeToProjectRoot, scopeFiles } from './state.js';
8
9
  export class SloopBridge extends EventEmitter {
9
10
  process = null;
10
11
  connected = false;
@@ -116,7 +117,7 @@ export class SloopBridge extends EventEmitter {
116
117
  });
117
118
  }
118
119
  setupMessageHandlers() {
119
- if (!this.process || !this.process.stdout)
120
+ if (!this.process?.stdout)
120
121
  return;
121
122
  this.process.stdout.on('data', (data) => {
122
123
  this.messageBuffer += data.toString();
@@ -132,7 +133,7 @@ export class SloopBridge extends EventEmitter {
132
133
  processMessages() {
133
134
  while (true) {
134
135
  // Look for Content-Length header
135
- const headerMatch = this.messageBuffer.match(/Content-Length: (\d+)\r?\n\r?\n/);
136
+ const headerMatch = /Content-Length: (\d+)\r?\n\r?\n/.exec(this.messageBuffer);
136
137
  if (!headerMatch)
137
138
  break;
138
139
  const contentLength = parseInt(headerMatch[1]);
@@ -157,179 +158,96 @@ export class SloopBridge extends EventEmitter {
157
158
  const timestamp = new Date().toISOString();
158
159
  console.error(`[DEBUG ${timestamp}] Received message:`, JSON.stringify(message, null, 2).substring(0, 1000));
159
160
  }
160
- // Handle requests FROM SLOOP (client RPC methods) - check method field FIRST
161
161
  // Requests have both id AND method, responses have id but no method
162
162
  if (message.id && message.method) {
163
163
  this.handleClientRequest(message);
164
- return;
165
164
  }
166
- // Handle responses to our requests (has id but no method)
167
- if (message.id && !message.method) {
168
- if (this.pendingRequests.has(message.id)) {
169
- const pending = this.pendingRequests.get(message.id);
170
- clearTimeout(pending.timeout);
171
- this.pendingRequests.delete(message.id);
172
- if (message.error) {
173
- // Log full error for debugging
174
- console.error('Full RPC Error:', JSON.stringify(message.error, null, 2).substring(0, 2000));
175
- pending.reject(new Error(message.error.message || 'RPC Error'));
176
- }
177
- else {
178
- console.error('[DEBUG] Resolving request', message.id, 'with result');
179
- pending.resolve(message.result);
180
- }
181
- }
165
+ else if (message.id && !message.method) {
166
+ this.handleResponse(message);
167
+ }
168
+ else if (!message.id && message.method) {
169
+ this.handleNotification(message);
170
+ }
171
+ }
172
+ handleResponse(message) {
173
+ if (!this.pendingRequests.has(message.id))
182
174
  return;
175
+ const pending = this.pendingRequests.get(message.id);
176
+ clearTimeout(pending.timeout);
177
+ this.pendingRequests.delete(message.id);
178
+ if (message.error) {
179
+ console.error('Full RPC Error:', JSON.stringify(message.error, null, 2).substring(0, 2000));
180
+ pending.reject(new Error(message.error.message || 'RPC Error'));
183
181
  }
184
- // Handle notifications from SLOOP (no id, has method)
185
- if (!message.id && message.method) {
186
- this.emit('notification', message);
187
- if (message.method === 'log') {
188
- this.emit('log', message.params);
189
- }
190
- else if (message.method === 'raiseIssues' && message.params) {
191
- const { analysisId, issuesByFileUri } = message.params;
192
- if (analysisId && issuesByFileUri) {
193
- this.issueCollector.addIssues(analysisId, issuesByFileUri);
194
- const count = Object.values(issuesByFileUri).reduce((sum, arr) => sum + arr.length, 0);
195
- console.error(`[SLOOP] Received raiseIssues: ${count} issues for analysis ${analysisId}`);
196
- }
197
- }
198
- else if (message.method === 'raiseHotspots' && message.params) {
199
- const { analysisId, hotspotsByFileUri } = message.params;
200
- if (analysisId && hotspotsByFileUri) {
201
- this.issueCollector.addHotspots(analysisId, hotspotsByFileUri);
202
- const count = Object.values(hotspotsByFileUri).reduce((sum, arr) => sum + arr.length, 0);
203
- console.error(`[SLOOP] Received raiseHotspots: ${count} hotspots for analysis ${analysisId}`);
204
- }
205
- }
182
+ else {
183
+ console.error('[DEBUG] Resolving request', message.id, 'with result');
184
+ pending.resolve(message.result);
206
185
  }
207
186
  }
208
- findFilesInDirectory(dir, baseDir) {
209
- if (!baseDir)
210
- baseDir = dir;
211
- const files = [];
212
- try {
213
- const items = readdirSync(dir);
214
- for (const item of items) {
215
- const fullPath = join(dir, item);
216
- const relativePath = relative(baseDir, fullPath);
217
- // Skip excluded directories
218
- if (relativePath.startsWith('node_modules') || relativePath.startsWith('.git') ||
219
- relativePath.startsWith('dist') || relativePath.startsWith('build')) {
220
- continue;
221
- }
222
- const stat = statSync(fullPath);
223
- if (stat.isDirectory()) {
224
- files.push(...this.findFilesInDirectory(fullPath, baseDir));
225
- }
226
- else if (stat.isFile()) {
227
- // Only include source files
228
- if (/\.(js|ts|py|java|html|css|php|go|rb)$/.test(item)) {
229
- files.push(`file://${fullPath}`);
230
- }
231
- }
232
- }
187
+ handleNotification(message) {
188
+ this.emit('notification', message);
189
+ const { method, params } = message;
190
+ switch (method) {
191
+ case 'log':
192
+ this.emit('log', params);
193
+ break;
194
+ case 'raiseIssues':
195
+ this.onRaiseIssues(params);
196
+ break;
197
+ case 'raiseHotspots':
198
+ this.onRaiseHotspots(params);
199
+ break;
200
+ case 'didChangeAnalysisReadiness':
201
+ this.onAnalysisReadiness(params);
202
+ break;
233
203
  }
234
- catch (err) {
235
- console.error('Error reading directory:', dir, err);
204
+ }
205
+ onRaiseIssues(params) {
206
+ const { analysisId, issuesByFileUri } = params ?? {};
207
+ if (!analysisId || !issuesByFileUri)
208
+ return;
209
+ this.issueCollector.addIssues(analysisId, issuesByFileUri);
210
+ const count = Object.values(issuesByFileUri).reduce((sum, arr) => sum + arr.length, 0);
211
+ console.error(`[SLOOP] Received raiseIssues: ${count} issues for analysis ${analysisId}`);
212
+ }
213
+ onRaiseHotspots(params) {
214
+ const { analysisId, hotspotsByFileUri } = params ?? {};
215
+ if (!analysisId || !hotspotsByFileUri)
216
+ return;
217
+ this.issueCollector.addHotspots(analysisId, hotspotsByFileUri);
218
+ const count = Object.values(hotspotsByFileUri).reduce((sum, arr) => sum + arr.length, 0);
219
+ console.error(`[SLOOP] Received raiseHotspots: ${count} hotspots for analysis ${analysisId}`);
220
+ }
221
+ onAnalysisReadiness(params) {
222
+ const { configurationScopeIds, areReadyForAnalysis } = params ?? {};
223
+ console.error(`[SLOOP] Analysis readiness changed: scopes=${configurationScopeIds}, ready=${areReadyForAnalysis}`);
224
+ if (!areReadyForAnalysis)
225
+ return;
226
+ for (const scopeId of configurationScopeIds) {
227
+ this.emit('scopeReady', scopeId);
236
228
  }
237
- return files;
238
229
  }
239
230
  handleClientRequest(request) {
240
231
  console.error(`[DEBUG] Handling client request: ${request.method}`);
241
- // Implement listFiles - SLOOP needs to know what files exist
232
+ // listFiles return only the files pre-registered in scopeFiles.
233
+ // IMPORTANT: Do NOT scan the project directory here. SLOOP calls listFiles
234
+ // during addConfigurationScope, so only the files the caller asked to analyse
235
+ // should be returned. Scanning caused 500+ file responses and hangs on real
236
+ // projects. Files are pre-registered in getOrCreateScope() before the scope
237
+ // is created. See scope.ts for the full sequencing explanation.
242
238
  if (request.method === 'listFiles') {
243
239
  const configScopeId = request.params?.configScopeId;
244
- const baseDir = process.cwd();
245
- const fileDtos = [];
246
- // Helper to detect language from extension
247
- const detectLanguage = (filePath) => {
248
- if (filePath.endsWith('.js'))
249
- return 'JS';
250
- if (filePath.endsWith('.ts'))
251
- return 'TS';
252
- if (filePath.endsWith('.py'))
253
- return 'PYTHON';
254
- if (filePath.endsWith('.java'))
255
- return 'JAVA';
256
- if (filePath.endsWith('.html'))
257
- return 'HTML';
258
- if (filePath.endsWith('.css'))
259
- return 'CSS';
260
- return null;
261
- };
262
- // Scan root directory for source files
263
- try {
264
- const rootItems = readdirSync(baseDir);
265
- for (const item of rootItems) {
266
- const fullPath = join(baseDir, item);
267
- try {
268
- const stat = statSync(fullPath);
269
- if (stat.isFile() && /\.(js|ts|py|java|html|css|php|go|rb)$/.test(item)) {
270
- const content = readFileSync(fullPath, 'utf-8');
271
- const relativePath = relative(baseDir, fullPath);
272
- const language = detectLanguage(fullPath);
273
- // Debug: Log first 200 chars of content for test files
274
- if (item === 'test-simple.js' || item === 'test-python.py') {
275
- console.error(`[DEBUG listFiles] ${item}: ${content.substring(0, 200)}`);
276
- }
277
- fileDtos.push({
278
- uri: `file://${fullPath}`,
279
- fsPath: fullPath,
280
- ideRelativePath: relativePath,
281
- configScopeId: configScopeId,
282
- isTest: false,
283
- charset: 'UTF-8',
284
- content: content,
285
- detectedLanguage: language,
286
- isUserDefined: true // CRITICAL: Must be true for SLOOP to analyze!
287
- });
288
- }
289
- else if (stat.isDirectory() && item === 'src') {
290
- // Only scan src directory recursively
291
- const srcFiles = this.findFilesInDirectory(fullPath);
292
- for (const fileUri of srcFiles) {
293
- const filePath = fileUri.replace('file://', '');
294
- try {
295
- const content = readFileSync(filePath, 'utf-8');
296
- const relativePath = relative(baseDir, filePath);
297
- const language = detectLanguage(filePath);
298
- fileDtos.push({
299
- uri: fileUri,
300
- fsPath: filePath,
301
- ideRelativePath: relativePath,
302
- configScopeId: configScopeId,
303
- isTest: relativePath.includes('test'),
304
- charset: 'UTF-8',
305
- content: content,
306
- detectedLanguage: language,
307
- isUserDefined: true // CRITICAL: Must be true for SLOOP to analyze!
308
- });
309
- }
310
- catch (readErr) {
311
- console.error(`Could not read file ${filePath}:`, readErr);
312
- }
313
- }
314
- }
315
- }
316
- catch (e) {
317
- // Skip files we can't access
318
- }
319
- }
320
- }
321
- catch (err) {
322
- console.error('Error listing files:', err);
323
- }
324
- console.error(`[DEBUG] Returning ${fileDtos.length} ClientFileDto objects for listFiles`);
240
+ const fileDtos = scopeFiles.get(configScopeId) || [];
241
+ console.error(`[DEBUG] listFiles for scope ${configScopeId}: returning ${fileDtos.length} registered files`);
325
242
  this.sendResponse(request.id, { files: fileDtos });
326
243
  return;
327
244
  }
328
245
  // Implement getBaseDir - SLOOP needs the base directory for the config scope
329
246
  if (request.method === 'getBaseDir') {
330
- // Return current working directory as base dir
331
- const basePath = process.cwd();
332
- this.sendResponse(request.id, { path: basePath });
247
+ const configScopeId = request.params?.configurationScopeId ?? request.params?.configScopeId;
248
+ const projectRoot = scopeToProjectRoot.get(configScopeId) || process.cwd();
249
+ console.error(`[DEBUG] getBaseDir for scope ${configScopeId}: ${projectRoot}`);
250
+ this.sendResponse(request.id, { path: projectRoot });
333
251
  return;
334
252
  }
335
253
  // Implement getFileExclusions - file patterns to exclude from analysis
@@ -526,8 +444,8 @@ export class SloopBridge extends EventEmitter {
526
444
  try {
527
445
  await this.sendRequest('shutdown');
528
446
  }
529
- catch (err) {
530
- // Ignore shutdown errors
447
+ catch {
448
+ console.error('[SLOOP] Shutdown request failed (process may already be exiting)');
531
449
  }
532
450
  this.process.kill();
533
451
  this.process = null;
@@ -542,6 +460,26 @@ export class SloopBridge extends EventEmitter {
542
460
  async listAllStandaloneRulesDefinitions() {
543
461
  return this.sendRequest('rules/listAllStandaloneRulesDefinitions');
544
462
  }
463
+ /**
464
+ * Wait for a scope to become ready for analysis.
465
+ * SLOOP emits didChangeAnalysisReadiness after processing addConfigurationScope.
466
+ */
467
+ waitForScopeReady(scopeId, timeoutMs = 30000) {
468
+ return new Promise((resolve, reject) => {
469
+ const timer = setTimeout(() => {
470
+ this.removeListener('scopeReady', onReady);
471
+ reject(new Error(`Timeout waiting for scope ${scopeId} to become ready`));
472
+ }, timeoutMs);
473
+ const onReady = (readyScopeId) => {
474
+ if (readyScopeId === scopeId) {
475
+ clearTimeout(timer);
476
+ this.removeListener('scopeReady', onReady);
477
+ resolve();
478
+ }
479
+ };
480
+ this.on('scopeReady', onReady);
481
+ });
482
+ }
545
483
  addConfigurationScope(scopeId, params = {}) {
546
484
  this.sendNotification('configuration/didAddConfigurationScopes', {
547
485
  addedScopes: [{
@@ -566,7 +504,11 @@ export class SloopBridge extends EventEmitter {
566
504
  console.error(`[ANALYSIS] Analysis ID: ${analysisId}`);
567
505
  const startTime = Date.now();
568
506
  // Register files in SLOOP's virtual file system before analysis
569
- const fileDtos = buildClientFileDtos(filePaths, configScopeId);
507
+ const projectRoot = scopeToProjectRoot.get(configScopeId);
508
+ const fileDtos = buildClientFileDtos(filePaths, configScopeId, projectRoot);
509
+ // Store so listFiles callback returns only these files, not a full directory scan
510
+ const existing = scopeFiles.get(configScopeId) || [];
511
+ scopeFiles.set(configScopeId, [...existing, ...fileDtos]);
570
512
  this.sendNotification('file/didUpdateFileSystem', {
571
513
  addedFiles: fileDtos,
572
514
  changedFiles: [],