@groma/scanner-csharp 0.1.0 → 0.1.2

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 (112) hide show
  1. package/README.md +13 -3
  2. package/dist/index.js +140 -62
  3. package/dist/worker/BuildHost-net472/Microsoft.Bcl.AsyncInterfaces.dll +0 -0
  4. package/dist/worker/BuildHost-net472/Microsoft.Build.Locator.dll +0 -0
  5. package/dist/worker/BuildHost-net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe +0 -0
  6. package/dist/worker/BuildHost-net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe.config +0 -0
  7. package/dist/worker/BuildHost-net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.Contracts.dll +0 -0
  8. package/dist/worker/BuildHost-net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.Contracts.pdb +0 -0
  9. package/dist/worker/BuildHost-net472/Microsoft.IO.Redist.dll +0 -0
  10. package/dist/worker/BuildHost-net472/System.Buffers.dll +0 -0
  11. package/dist/worker/BuildHost-net472/System.IO.Pipelines.dll +0 -0
  12. package/dist/worker/BuildHost-net472/System.Memory.dll +0 -0
  13. package/dist/worker/BuildHost-net472/System.Numerics.Vectors.dll +0 -0
  14. package/dist/worker/BuildHost-net472/System.Runtime.CompilerServices.Unsafe.dll +0 -0
  15. package/dist/worker/BuildHost-net472/System.Text.Encodings.Web.dll +0 -0
  16. package/dist/worker/BuildHost-net472/System.Text.Json.dll +0 -0
  17. package/dist/worker/BuildHost-net472/System.Threading.Tasks.Extensions.dll +0 -0
  18. package/dist/worker/BuildHost-netcore/Microsoft.Build.Locator.dll +0 -0
  19. package/dist/worker/BuildHost-netcore/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.deps.json +0 -0
  20. package/dist/worker/BuildHost-netcore/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll +0 -0
  21. package/dist/worker/BuildHost-netcore/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.runtimeconfig.json +0 -0
  22. package/dist/worker/BuildHost-netcore/Microsoft.CodeAnalysis.Workspaces.MSBuild.Contracts.dll +0 -0
  23. package/dist/worker/BuildHost-netcore/Microsoft.CodeAnalysis.Workspaces.MSBuild.Contracts.pdb +0 -0
  24. package/dist/worker/Groma.CSharpScanner.dll +0 -0
  25. package/dist/worker/Groma.CSharpScanner.pdb +0 -0
  26. package/dist/worker/Humanizer.dll +0 -0
  27. package/dist/worker/Microsoft.Build.Locator.dll +0 -0
  28. package/dist/worker/Microsoft.CodeAnalysis.CSharp.Workspaces.dll +0 -0
  29. package/dist/worker/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  30. package/dist/worker/Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.dll +0 -0
  31. package/dist/worker/Microsoft.CodeAnalysis.Workspaces.MSBuild.Contracts.dll +0 -0
  32. package/dist/worker/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll +0 -0
  33. package/dist/worker/Microsoft.CodeAnalysis.Workspaces.dll +0 -0
  34. package/dist/worker/Microsoft.CodeAnalysis.dll +0 -0
  35. package/dist/worker/Microsoft.Extensions.DependencyInjection.Abstractions.dll +0 -0
  36. package/dist/worker/Microsoft.Extensions.DependencyInjection.dll +0 -0
  37. package/dist/worker/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
  38. package/dist/worker/Microsoft.Extensions.Logging.dll +0 -0
  39. package/dist/worker/Microsoft.Extensions.Options.dll +0 -0
  40. package/dist/worker/Microsoft.Extensions.Primitives.dll +0 -0
  41. package/dist/worker/Microsoft.VisualStudio.SolutionPersistence.dll +0 -0
  42. package/dist/worker/System.Composition.AttributedModel.dll +0 -0
  43. package/dist/worker/System.Composition.Convention.dll +0 -0
  44. package/dist/worker/System.Composition.Hosting.dll +0 -0
  45. package/dist/worker/System.Composition.Runtime.dll +0 -0
  46. package/dist/worker/System.Composition.TypedParts.dll +0 -0
  47. package/dist/worker/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  48. package/dist/worker/cs/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  49. package/dist/worker/cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  50. package/dist/worker/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  51. package/dist/worker/cs/Microsoft.CodeAnalysis.resources.dll +0 -0
  52. package/dist/worker/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  53. package/dist/worker/de/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  54. package/dist/worker/de/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  55. package/dist/worker/de/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  56. package/dist/worker/de/Microsoft.CodeAnalysis.resources.dll +0 -0
  57. package/dist/worker/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  58. package/dist/worker/es/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  59. package/dist/worker/es/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  60. package/dist/worker/es/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  61. package/dist/worker/es/Microsoft.CodeAnalysis.resources.dll +0 -0
  62. package/dist/worker/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  63. package/dist/worker/fr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  64. package/dist/worker/fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  65. package/dist/worker/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  66. package/dist/worker/fr/Microsoft.CodeAnalysis.resources.dll +0 -0
  67. package/dist/worker/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  68. package/dist/worker/it/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  69. package/dist/worker/it/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  70. package/dist/worker/it/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  71. package/dist/worker/it/Microsoft.CodeAnalysis.resources.dll +0 -0
  72. package/dist/worker/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  73. package/dist/worker/ja/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  74. package/dist/worker/ja/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  75. package/dist/worker/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  76. package/dist/worker/ja/Microsoft.CodeAnalysis.resources.dll +0 -0
  77. package/dist/worker/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  78. package/dist/worker/ko/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  79. package/dist/worker/ko/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  80. package/dist/worker/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  81. package/dist/worker/ko/Microsoft.CodeAnalysis.resources.dll +0 -0
  82. package/dist/worker/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  83. package/dist/worker/pl/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  84. package/dist/worker/pl/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  85. package/dist/worker/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  86. package/dist/worker/pl/Microsoft.CodeAnalysis.resources.dll +0 -0
  87. package/dist/worker/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  88. package/dist/worker/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  89. package/dist/worker/pt-BR/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  90. package/dist/worker/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  91. package/dist/worker/pt-BR/Microsoft.CodeAnalysis.resources.dll +0 -0
  92. package/dist/worker/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  93. package/dist/worker/ru/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  94. package/dist/worker/ru/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  95. package/dist/worker/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  96. package/dist/worker/ru/Microsoft.CodeAnalysis.resources.dll +0 -0
  97. package/dist/worker/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  98. package/dist/worker/tr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  99. package/dist/worker/tr/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  100. package/dist/worker/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  101. package/dist/worker/tr/Microsoft.CodeAnalysis.resources.dll +0 -0
  102. package/dist/worker/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  103. package/dist/worker/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  104. package/dist/worker/zh-Hans/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  105. package/dist/worker/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  106. package/dist/worker/zh-Hans/Microsoft.CodeAnalysis.resources.dll +0 -0
  107. package/dist/worker/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  108. package/dist/worker/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  109. package/dist/worker/zh-Hant/Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +0 -0
  110. package/dist/worker/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  111. package/dist/worker/zh-Hant/Microsoft.CodeAnalysis.resources.dll +0 -0
  112. package/package.json +2 -3
package/README.md CHANGED
@@ -27,7 +27,7 @@ See the [shared configuration contract](../creating-a-plugin.md#scanner-settings
27
27
 
28
28
  Run `dotnet restore Library.csproj` from that input directory, then run `groma scan` from the repository root. Restore uses the project's normal NuGet settings and credentials. On macOS, use a relative restore input from its directory so `/var` and `/private/var` aliases do not enter one restore graph as separate project paths.
29
29
 
30
- Install a prepared local package with `groma scanner add /path/to/csharp-scanner-package`. Release publication is separate from local qualification. The package also exports `checkCSharpReadiness(repositoryRoot, settings)`, used through the same input/tool checks as scanning. It returns the selected input and SDK version; successful readiness does not prove dependency restore or compilation. A missing worker means the package needs preparation; missing tooling or compilation errors must be fixed before scanning can replace architecture evidence.
30
+ Install a prepared local package with `groma scanner add /path/to/csharp-scanner-package`. Release publication is separate from local qualification. The package also exports `checkCSharpReadiness(repositoryRoot, { input })`, used through the same input/tool checks as scanning. It returns the selected input and SDK version; successful readiness does not prove dependency restore or compilation. A missing worker means the package needs preparation; missing tooling or compilation errors must be fixed before scanning can replace architecture evidence.
31
31
 
32
32
  ## Supported input and evidence
33
33
 
@@ -35,14 +35,14 @@ The selected qualification example is FluentValidation 12.0.0, commit `5365d9294
35
35
 
36
36
  Inputs are SDK-style `.csproj`, `.sln`, and `.slnx` files. When input is omitted, one root solution takes precedence over root projects. Multiple candidates require explicit selection. Standard .NET, Web and Worker SDK project headers are accepted, but this is not general framework qualification. Mixed-language graphs, legacy project formats, multiple target-framework contexts, and a file shared by multiple loaded project contexts are rejected.
37
37
 
38
- Each physical C# source has one inventory record. Generated `bin` and `obj` sources are excluded. Roslyn resolves overloads, generic methods, extensions, partial implementations and direct calls. Virtual, interface and delegate dispatch retain uncertainty where the runtime provider is not established. Implicit calls, initializers, generated operations, receiver/delegate value flow, dependency injection and network protocols are not resolved.
38
+ Each physical C# source inside the repository has one inventory record. Generated `bin` and `obj` sources are excluded. SDK and package source files outside the repository remain compiler context, including validation, but do not produce file or operation evidence. Project references must stay inside the repository. Roslyn resolves overloads, generic methods, extensions, partial implementations and direct calls. Virtual, interface and delegate dispatch retain uncertainty where the runtime provider is not established. Implicit calls, initializers, generated operations, receiver/delegate value flow, dependency injection and network protocols are not resolved.
39
39
 
40
40
  Solutions and projects are source roots, with each project linked to its solution
41
41
  when a solution is selected. File records identify their project root. A directly
42
42
  selected project and its loaded project references are top-level source roots.
43
43
  Root membership and operations are temporary evidence. They are not C4 components or proof of business collaborations. Core owns curated source membership and relationship selection; ordinary Markdown readers retain readable descriptions and links under the existing OKF application profile. This plugin introduces no architecture metadata or map level.
44
44
 
45
- `settings` also accepts `configuration` (default `Debug`), `maxProjects` (128), `maxFiles` (20000), and `timeoutSeconds` (120). Exceeded limits fail the scan; they never publish truncated evidence. Any enabled scanner failure prevents reconciliation and preserves the prior map.
45
+ `settings` also accepts `configuration` (default `Debug`), `maxProjects` (128), `maxFiles` (20000), and `timeoutSeconds` (120). Exceeded limits fail the scan; they never publish truncated evidence. A failed scanner preserves its saved evidence; other scanners can still update the map.
46
46
 
47
47
  ## Contributor package build
48
48
 
@@ -53,3 +53,13 @@ bun scripts/package-csharp-scanner.ts
53
53
  ```
54
54
 
55
55
  The build bundles the adapter and publishes a framework-dependent worker into the package. It has no installation scripts and does not include a private SDK. Run the Roslyn tests with `dotnet test plugins/scanners/csharp/dotnet/test/Groma.CSharpScanner.Tests.csproj`.
56
+
57
+ ## Nested projects
58
+
59
+ From the repository root, the scanner finds tracked and unignored `.sln`, `.slnx`
60
+ and `.csproj` files. Solutions are loaded first. Project roots returned by Roslyn
61
+ prevent a solution member or project reference from being scanned again as a
62
+ standalone input. Independent projects are scanned as additional inputs. Each
63
+ input selects its own installed SDK; all evidence paths stay relative to the
64
+ repository. `settings.input` still selects one explicit solution or project.
65
+ Any selected input failure fails the C# observation. Other scanners can still update the map.
package/dist/index.js CHANGED
@@ -1,8 +1,86 @@
1
1
  // @bun
2
- // plugins/scanners/csharp/src/adapter.ts
3
- import { access } from "fs/promises";
2
+ // plugins/scanners/csharp/src/index.ts
3
+ import path4 from "path";
4
+
5
+ // plugins/scanners/csharp/src/config.ts
6
+ import { stat } from "fs/promises";
4
7
  import path2 from "path";
5
- import { fileURLToPath } from "url";
8
+
9
+ // plugins/scanners/projects.ts
10
+ import { execFile } from "child_process";
11
+ import { existsSync } from "fs";
12
+ import path from "path";
13
+ import { promisify } from "util";
14
+ var execute = promisify(execFile);
15
+ var excluded = new Set([
16
+ ".git",
17
+ "node_modules",
18
+ "vendor",
19
+ "target",
20
+ "dist",
21
+ "build",
22
+ "bin",
23
+ "obj",
24
+ ".gradle",
25
+ ".angular",
26
+ "coverage",
27
+ "generated",
28
+ "groma",
29
+ ".groma"
30
+ ]);
31
+ async function projectFiles(root, matches) {
32
+ const { stdout } = await execute("git", ["-C", root, "ls-files", "-z", "--cached", "--others", "--exclude-standard"], { maxBuffer: 64 * 1024 * 1024 });
33
+ return [...new Set(stdout.split("\x00").filter((file) => file && matches(file) && !file.split("/").some((part) => excluded.has(part)) && existsSync(path.join(root, file))))].sort();
34
+ }
35
+
36
+ // plugins/scanners/csharp/src/config.ts
37
+ var defaults = { configuration: "Debug", maxProjects: 128, maxFiles: 20000, timeoutSeconds: 120 };
38
+ var configName = "csharp scanner settings";
39
+ function positiveInteger(value, key, fallback) {
40
+ if (value === undefined)
41
+ return fallback;
42
+ if (!Number.isSafeInteger(value) || Number(value) < 1)
43
+ throw new Error(`${configName}: ${key} must be a positive integer`);
44
+ return Number(value);
45
+ }
46
+ function optionalText(value, key) {
47
+ if (value === undefined)
48
+ return;
49
+ if (typeof value !== "string" || !value.trim())
50
+ throw new Error(`${configName}: ${key} must be nonempty text`);
51
+ return value;
52
+ }
53
+ function parseCSharpSettings(config = {}) {
54
+ for (const key of Object.keys(config)) {
55
+ if (!["input", ...Object.keys(defaults)].includes(key))
56
+ throw new Error(`${configName}: unknown setting ${key}`);
57
+ }
58
+ const input = optionalText(config.input, "input");
59
+ const configuration = optionalText(config.configuration, "configuration");
60
+ return {
61
+ ...input === undefined ? {} : { input },
62
+ configuration: configuration ?? defaults.configuration,
63
+ maxProjects: positiveInteger(config.maxProjects, "maxProjects", defaults.maxProjects),
64
+ maxFiles: positiveInteger(config.maxFiles, "maxFiles", defaults.maxFiles),
65
+ timeoutSeconds: positiveInteger(config.timeoutSeconds, "timeoutSeconds", defaults.timeoutSeconds)
66
+ };
67
+ }
68
+ async function validateInput(root, selected) {
69
+ const full = path2.resolve(root, selected);
70
+ const relative = path2.relative(root, full);
71
+ if (relative === ".." || relative.startsWith(`..${path2.sep}`) || path2.isAbsolute(relative))
72
+ throw new Error("C# scan input must stay inside the repository");
73
+ if (!/\.(?:csproj|slnx?)$/i.test(full) || !(await stat(full)).isFile())
74
+ throw new Error("C# input must be an existing .csproj, .sln, or .slnx file");
75
+ return full;
76
+ }
77
+ async function csharpInputs(root, settings) {
78
+ const config = parseCSharpSettings(settings);
79
+ if (config.input)
80
+ return [await validateInput(root, config.input)];
81
+ const files = await projectFiles(root, (file) => /\.(?:csproj|slnx?)$/i.test(file));
82
+ return [...files.filter((file) => /\.slnx?$/i.test(file)), ...files.filter((file) => /\.csproj$/i.test(file))].map((file) => path2.resolve(root, file));
83
+ }
6
84
 
7
85
  // packages/scanner/src/index.ts
8
86
  function compare(...values) {
@@ -258,60 +336,43 @@ function sourcePosition(position) {
258
336
  return { position: Number(position) };
259
337
  }
260
338
 
261
- // plugins/scanners/csharp/src/config.ts
262
- import { readdir, stat } from "fs/promises";
263
- import path from "path";
264
- var defaults = { configuration: "Debug", maxProjects: 128, maxFiles: 20000, timeoutSeconds: 120 };
265
- var configName = "csharp scanner settings";
266
- function positiveInteger(value, key, fallback) {
267
- if (value === undefined)
268
- return fallback;
269
- if (!Number.isSafeInteger(value) || Number(value) < 1)
270
- throw new Error(`${configName}: ${key} must be a positive integer`);
271
- return Number(value);
272
- }
273
- function optionalText(value, key) {
274
- if (value === undefined)
339
+ // plugins/scanners/observations.ts
340
+ function combineObservations(parts) {
341
+ if (!parts.length)
275
342
  return;
276
- if (typeof value !== "string" || !value.trim())
277
- throw new Error(`${configName}: ${key} must be nonempty text`);
278
- return value;
279
- }
280
- function parseCSharpSettings(config = {}) {
281
- for (const key of Object.keys(config)) {
282
- if (!["input", ...Object.keys(defaults)].includes(key))
283
- throw new Error(`${configName}: unknown setting ${key}`);
343
+ const roots = [];
344
+ const files = new Map;
345
+ const operations = [];
346
+ const invocations = [];
347
+ const diagnostics = [];
348
+ for (const { key, observation } of parts) {
349
+ const id = (value) => JSON.stringify([key, value]);
350
+ roots.push(...observation.roots.map((root) => ({ ...root, id: id(root.id), ...root.parent ? { parent: id(root.parent) } : {} })));
351
+ for (const source of observation.files) {
352
+ const combined = files.get(source.file) ?? { file: source.file, roots: [], symbols: [] };
353
+ combined.roots.push(...source.roots.map(id));
354
+ combined.symbols.push(...source.symbols.map((symbol) => ({ ...symbol, id: id(symbol.id) })));
355
+ files.set(source.file, combined);
356
+ }
357
+ operations.push(...(observation.operations ?? []).map((operation) => ({ ...operation, id: id(operation.id) })));
358
+ invocations.push(...(observation.invocations ?? []).map((call) => ({ ...call, source: id(call.source), targets: call.targets.map(id) })));
359
+ diagnostics.push(...observation.diagnostics);
284
360
  }
285
- const input = optionalText(config.input, "input");
286
- const configuration = optionalText(config.configuration, "configuration");
287
- return {
288
- ...input === undefined ? {} : { input },
289
- configuration: configuration ?? defaults.configuration,
290
- maxProjects: positiveInteger(config.maxProjects, "maxProjects", defaults.maxProjects),
291
- maxFiles: positiveInteger(config.maxFiles, "maxFiles", defaults.maxFiles),
292
- timeoutSeconds: positiveInteger(config.timeoutSeconds, "timeoutSeconds", defaults.timeoutSeconds)
293
- };
294
- }
295
- async function findCSharpInput(root, selected) {
296
- if (selected !== undefined)
297
- return validateInput(root, selected);
298
- const files = (await readdir(root, { withFileTypes: true })).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
299
- const solutions = files.filter((file) => /\.slnx?$/i.test(file));
300
- const candidates = solutions.length ? solutions : files.filter((file) => /\.csproj$/i.test(file));
301
- if (candidates.length > 1)
302
- throw new Error(`Several C# scan inputs exist; set settings.input on the csharp entry in scanners.json: ${candidates.join(", ")}`);
303
- return candidates.length ? path.resolve(root, candidates[0]) : undefined;
304
- }
305
- async function validateInput(root, selected) {
306
- const full = path.resolve(root, selected);
307
- const relative = path.relative(root, full);
308
- if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))
309
- throw new Error("C# scan input must stay inside the repository");
310
- if (!/\.(?:csproj|slnx?)$/i.test(full) || !(await stat(full)).isFile())
311
- throw new Error("C# input must be an existing .csproj, .sln, or .slnx file");
312
- return full;
361
+ return createScanObservation({
362
+ scanner: parts[0].observation.scanner,
363
+ roots,
364
+ files: [...files.values()],
365
+ operations,
366
+ invocations,
367
+ diagnostics
368
+ });
313
369
  }
314
370
 
371
+ // plugins/scanners/csharp/src/adapter.ts
372
+ import { access } from "fs/promises";
373
+ import path3 from "path";
374
+ import { fileURLToPath } from "url";
375
+
315
376
  // plugins/scanners/csharp/src/process.ts
316
377
  import { spawn } from "child_process";
317
378
  function stopTree(child) {
@@ -390,13 +451,13 @@ async function requireWorker(file = workerDll) {
390
451
  }
391
452
  }
392
453
  async function prepareCSharpScan(repositoryRoot, settings, dotnet, worker) {
393
- const root = path2.resolve(repositoryRoot);
454
+ const root = path3.resolve(repositoryRoot);
394
455
  const config = parseCSharpSettings(settings);
395
- const input = await findCSharpInput(root, config.input);
396
- if (!input)
397
- throw new Error("No C# input was selected. Set settings.input on the csharp entry in scanners.json or disable the csharp scanner.");
456
+ if (!config.input)
457
+ throw new Error("C# analysis requires a selected project or solution input.");
458
+ const input = await validateInput(root, config.input);
398
459
  await requireWorker(worker);
399
- const options = { cwd: path2.dirname(input), timeoutSeconds: config.timeoutSeconds };
460
+ const options = { cwd: path3.dirname(input), timeoutSeconds: config.timeoutSeconds };
400
461
  let sdkVersion;
401
462
  try {
402
463
  sdkVersion = (await run(dotnet, ["--version"], options)).stdout.trim();
@@ -425,7 +486,7 @@ async function scanCSharpSource(repositoryRoot, settings = {}, dotnet = process.
425
486
  String(config.maxProjects),
426
487
  "--max-files",
427
488
  String(config.maxFiles)
428
- ], { cwd: path2.dirname(input), timeoutSeconds: config.timeoutSeconds });
489
+ ], { cwd: path3.dirname(input), timeoutSeconds: config.timeoutSeconds });
429
490
  return parseScanObservation(stdout);
430
491
  }
431
492
 
@@ -446,10 +507,27 @@ var scanner = {
446
507
  ].map((pattern) => pattern.replace(/[a-z]/g, (letter) => `[${letter}${letter.toUpperCase()}]`)),
447
508
  exclude: ["**/[bB][iI][nN]/**", "**/[oO][bB][jJ]/**"]
448
509
  },
449
- checkReadiness: async (root, settings) => {
450
- await checkCSharpReadiness(root, settings);
510
+ checkReadiness: async (root, settings = {}) => {
511
+ const inputs = await csharpInputs(root, settings);
512
+ if (!inputs.length)
513
+ throw new Error("No C# project or solution was found.");
514
+ for (const input of inputs)
515
+ await checkCSharpReadiness(root, { ...settings, input });
451
516
  },
452
- scan: scanCSharpSource
517
+ scan: async (root, settings = {}) => {
518
+ const parts = [];
519
+ const covered = new Set;
520
+ for (const input of await csharpInputs(root, settings)) {
521
+ if (covered.has(input))
522
+ continue;
523
+ const observation = await scanCSharpSource(root, { ...settings, input });
524
+ for (const project of observation.roots)
525
+ if (project.file)
526
+ covered.add(path4.resolve(root, project.file));
527
+ parts.push({ key: path4.relative(root, input).split(path4.sep).join("/"), observation });
528
+ }
529
+ return combineObservations(parts);
530
+ }
453
531
  };
454
532
  var src_default = scanner;
455
533
  export {
File without changes
File without changes
File without changes
Binary file
Binary file
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groma/scanner-csharp",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,8 +35,7 @@
35
35
  }
36
36
  ],
37
37
  "compatibility": {
38
- "groma": "^0.3.0",
39
- "technologyVersions": {}
38
+ "groma": "^0.3.0"
40
39
  }
41
40
  }
42
41
  }