Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a8efb8226 |
@@ -143,25 +143,27 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async (
|
||||
const selectedFileCount =
|
||||
fileSet.files.length - (fileSet.source_selection?.unselected_files ?? 0);
|
||||
let selectedFileIndex = 0;
|
||||
// Caller-excluded sources are never analyzed, so neither cancellation nor
|
||||
// another interruption describes them.
|
||||
const recordOutsideSelection = (file: JavaScriptArtifactFile): boolean => {
|
||||
if (file.text.included || file.text.reason !== "outside-analysis-scope")
|
||||
return false;
|
||||
state.files.push({ file, javascript: null, semantic: null });
|
||||
if (file.kind === "javascript")
|
||||
projection.recordUnavailableFile(
|
||||
file,
|
||||
"Source was not analyzed because it is outside the caller-selected source_paths.",
|
||||
null,
|
||||
"incomplete-module",
|
||||
);
|
||||
return true;
|
||||
};
|
||||
for (const file of fileSet.files) {
|
||||
try {
|
||||
await setImmediate();
|
||||
if (signal?.aborted === true)
|
||||
throw new AnalysisCancelledError("analyze_javascript_application");
|
||||
if (
|
||||
!file.text.included &&
|
||||
file.text.reason === "outside-analysis-scope"
|
||||
) {
|
||||
state.files.push({ file, javascript: null, semantic: null });
|
||||
if (file.kind === "javascript")
|
||||
projection.recordUnavailableFile(
|
||||
file,
|
||||
"Source was not analyzed because it is outside the caller-selected source_paths.",
|
||||
null,
|
||||
"incomplete-module",
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (recordOutsideSelection(file)) continue;
|
||||
await beforeFile(file, selectedFileIndex++, selectedFileCount);
|
||||
if (file.kind !== "javascript" || !file.text.included) {
|
||||
const steps = analyzeArtifactFileSteps(file, {
|
||||
@@ -252,7 +254,7 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async (
|
||||
: cause instanceof AnalysisError
|
||||
? cause
|
||||
: null;
|
||||
if (interruption !== null) {
|
||||
if (interruption !== null && !recordOutsideSelection(file)) {
|
||||
state.files.push({
|
||||
file,
|
||||
javascript: null,
|
||||
@@ -286,21 +288,8 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async (
|
||||
: null,
|
||||
};
|
||||
for (const file of fileSet.files) {
|
||||
if (analyzedPaths.has(file.path)) continue;
|
||||
if (
|
||||
!file.text.included &&
|
||||
file.text.reason === "outside-analysis-scope"
|
||||
) {
|
||||
state.files.push({ file, javascript: null, semantic: null });
|
||||
if (file.kind === "javascript")
|
||||
projection.recordUnavailableFile(
|
||||
file,
|
||||
"Source was not analyzed because it is outside the caller-selected source_paths.",
|
||||
null,
|
||||
"incomplete-module",
|
||||
);
|
||||
if (analyzedPaths.has(file.path) || recordOutsideSelection(file))
|
||||
continue;
|
||||
}
|
||||
state.files.push({
|
||||
file,
|
||||
javascript: null,
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import { analyzeAndAdoptJavaScriptArtifactFiles } from "../../../../src/application/javascript/JavaScriptArtifactAnalysis.js";
|
||||
import { createJavaScriptSemanticGraphProjection } from "../../../../src/application/javascript/JavaScriptSemanticGraphBuilder.js";
|
||||
import { readJavaScriptArtifactFiles } from "../../../../src/artifacts/javascript/JavaScriptArtifactFiles.js";
|
||||
import { createJavaScriptArtifactReader } from "../../../../src/artifacts/javascript/JavaScriptArtifactReader.js";
|
||||
import { createJavaScriptSourceAnalysis } from "../../../../src/artifacts/javascript/JavaScriptSourceAnalysis.js";
|
||||
import { JAVASCRIPT_ANALYSIS_RESOURCE_DEFAULTS } from "../../../../src/domain/javascript/javascriptAnalysisResourceControls.js";
|
||||
import {
|
||||
scanCanonicalArtifactInventory,
|
||||
withArtifactResourceScope,
|
||||
} from "../../../fixtures/artifactInventory.js";
|
||||
import { writeJavaScriptSourceSelectionFixture } from "../../../fixtures/javascriptSourceSelection.js";
|
||||
import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js";
|
||||
|
||||
it("keeps unselected sources outside the selection when cancellation follows the last selected source", async () => {
|
||||
const root = await createTestTempDirectory("rea-js-selected-late-cancel-");
|
||||
await writeJavaScriptSourceSelectionFixture(root);
|
||||
const snapshot = await scanCanonicalArtifactInventory(root, {});
|
||||
const reader = createJavaScriptArtifactReader(root, "directory");
|
||||
const worker = createJavaScriptSourceAnalysis(
|
||||
JAVASCRIPT_ANALYSIS_RESOURCE_DEFAULTS,
|
||||
1,
|
||||
);
|
||||
try {
|
||||
const files = await withArtifactResourceScope((scope) =>
|
||||
readJavaScriptArtifactFiles(reader, snapshot, scope, undefined, [
|
||||
"main.mjs",
|
||||
]),
|
||||
);
|
||||
const controller = new AbortController();
|
||||
// Cancel after the only selected source completes, before the loop
|
||||
// reaches the first unselected source.
|
||||
const { analysis, interruption } =
|
||||
await analyzeAndAdoptJavaScriptArtifactFiles(
|
||||
files,
|
||||
{
|
||||
analyze: async (file, budget, signal) => {
|
||||
const result = await worker.analyze(file, budget, signal);
|
||||
controller.abort();
|
||||
return result;
|
||||
},
|
||||
},
|
||||
createJavaScriptSemanticGraphProjection(),
|
||||
async () => {},
|
||||
controller.signal,
|
||||
);
|
||||
|
||||
expect(interruption?._tag).toBe("AnalysisCancelledError");
|
||||
const unselected = analysis.files.filter(
|
||||
({ file }) =>
|
||||
!file.text.included && file.text.reason === "outside-analysis-scope",
|
||||
);
|
||||
expect(unselected).toHaveLength(5);
|
||||
expect(
|
||||
unselected.filter((entry) => entry.analysis_failure !== undefined),
|
||||
).toEqual([]);
|
||||
} finally {
|
||||
await worker.close();
|
||||
await reader.close();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user