diff --git a/extractors/cds/tools/cds-extractor.ts b/extractors/cds/tools/cds-extractor.ts index d18a45a0d..ba947d1c4 100644 --- a/extractors/cds/tools/cds-extractor.ts +++ b/extractors/cds/tools/cds-extractor.ts @@ -3,17 +3,16 @@ import { join } from 'path'; import { sync as globSync } from 'glob'; import { orchestrateCompilation } from './src/cds/compiler'; -import { buildCdsProjectDependencyGraph } from './src/cds/parser'; -import { runJavaScriptExtractor } from './src/codeql'; +import { buildCdsProjectDependencyGraph, type CdsDependencyGraph } from './src/cds/parser'; +import { handleEarlyExit, runJavaScriptExtractionWithMarker } from './src/codeql'; import { addCompilationDiagnostic, addDependencyGraphDiagnostic, addDependencyInstallationDiagnostic, addEnvironmentSetupDiagnostic, - addJavaScriptExtractorDiagnostic, addNoCdsProjectsDiagnostic, } from './src/diagnostics'; -import { configureLgtmIndexFilters, setupAndValidateEnvironment } from './src/environment'; +import { setupAndValidateEnvironment } from './src/environment'; import { cdsExtractorLog, generateStatusReport, @@ -27,31 +26,28 @@ import { import { cacheInstallDependencies } from './src/packageManager'; import { validateArguments } from './src/utils'; -// Validate the script arguments. +// ============================================================================ +// Main Extraction Flow +// ============================================================================ + +// Validate arguments const validationResult = validateArguments(process.argv); if (!validationResult.isValid) { console.warn(validationResult.usageMessage); - // For invalid arguments, we can't proceed but we also can't add diagnostics since we don't have - // the necessary context (sourceRoot, codeqlExePath). Log the issue and exit gracefully. console.log( `CDS extractor terminated due to invalid arguments: ${validationResult.usageMessage}`, ); console.log(`Completed run of the cds-extractor.js script for the CDS extractor.`); - process.exit(0); // Use exit code 0 to not fail the overall JavaScript extractor + process.exit(0); } -// Get the validated and sanitized arguments. const { sourceRoot } = validationResult.args!; -// Initialize the unified logging system with the source root directory. +// Initialize logging setSourceRootDirectory(sourceRoot); - -// Log the start of the CDS extractor session as a whole. logExtractorStart(sourceRoot); -// Setup the environment and validate all requirements first, before changing -// directory back to the "sourceRoot" directory. This ensures we can properly locate -// the CodeQL tools. +// Setup and validate environment logPerformanceTrackingStart('Environment Setup'); const { success: envSetupSuccess, @@ -64,25 +60,18 @@ logPerformanceTrackingStop('Environment Setup'); if (!envSetupSuccess) { const codeqlExe = platformInfo.isWindows ? 'codeql.exe' : 'codeql'; - const errorMessage = `'${codeqlExe} database index-files --language cds' terminated early due to: ${errorMessages.join( - ', ', - )}.`; - + const errorMessage = `'${codeqlExe} database index-files --language cds' terminated early due to: ${errorMessages.join(', ')}.`; cdsExtractorLog('warn', errorMessage); - // Add diagnostic for environment setup failure if we have a codeqlExePath if (codeqlExePath) { addEnvironmentSetupDiagnostic(sourceRoot, errorMessage, codeqlExePath); } - // Continue with a warning instead of exiting - let JavaScript extractor proceed logExtractorStop( false, 'Warning: Environment setup failed, continuing with limited functionality', ); } else { - // Force this script, and any process it spawns, to use the project (source) root - // directory as the current working directory. process.chdir(sourceRoot); } @@ -91,17 +80,9 @@ cdsExtractorLog( `CodeQL CDS extractor using autobuild mode for scan of project source root directory '${sourceRoot}'.`, ); +// Build CDS project dependency graph cdsExtractorLog('info', 'Building CDS project dependency graph...'); - -// Build the CDS project `dependencyGraph` as the foundation for the extraction process. -// This graph will contain all discovered CDS projects, their dependencies, the `.cds` -// files discovered within each project, the expected `.cds.json` files for each project -// and the compilation status of such `.cds.json` files. -// -// The `dependencyGraph` will be updated as CDS extractor phases progress, allowing for -// a single data structure to be used for planning, execution, retries (i.e. error handling), -// debugging, and final reporting. -let dependencyGraph; +let dependencyGraph: CdsDependencyGraph; try { logPerformanceTrackingStart('Dependency Graph Build'); @@ -113,7 +94,7 @@ try { `${dependencyGraph.projects.size} projects, ${dependencyGraph.statusSummary.totalCdsFiles} CDS files`, ); - // Log details about discovered projects for debugging + // Log project details if (dependencyGraph.projects.size > 0) { for (const [projectDir, project] of dependencyGraph.projects.entries()) { cdsExtractorLog( @@ -122,11 +103,12 @@ try { ); } } else { + // No CDS projects detected - try direct file search as diagnostic cdsExtractorLog( 'error', 'No CDS projects were detected. This is an unrecoverable error as there is nothing to scan.', ); - // Let's also try to find CDS files directly as a backup check + try { const allCdsFiles = Array.from( new Set([ @@ -139,6 +121,7 @@ try { 'info', `Direct search found ${allCdsFiles.length} CDS files in the source tree.`, ); + if (allCdsFiles.length > 0) { cdsExtractorLog( 'info', @@ -158,160 +141,96 @@ try { cdsExtractorLog('warn', `Could not perform direct CDS file search: ${String(globError)}`); } - // Add diagnostic warning for no CDS projects detected const warningMessage = 'No CDS projects were detected. This may be expected if the source does not contain CAP/CDS projects.'; if (codeqlExePath) { addNoCdsProjectsDiagnostic(sourceRoot, warningMessage, codeqlExePath); } - // Continue instead of exiting - let JavaScript extractor proceed with non-CDS files logExtractorStop(false, 'Warning: No CDS projects detected, skipping CDS-specific processing'); - - // Skip the rest of CDS processing and go directly to JavaScript extraction - configureLgtmIndexFilters(); - - // Run CodeQL's JavaScript extractor to process any remaining files - logPerformanceTrackingStart('JavaScript Extraction'); - const extractorResult = runJavaScriptExtractor( + handleEarlyExit( sourceRoot, - autobuildScriptPath || '', // Use empty string if autobuildScriptPath is undefined + autobuildScriptPath || '', codeqlExePath, + 'JavaScript extraction completed (CDS processing was skipped)', ); - logPerformanceTrackingStop('JavaScript Extraction'); - - if (!extractorResult.success && extractorResult.error) { - cdsExtractorLog('error', `Error running JavaScript extractor: ${extractorResult.error}`); - if (codeqlExePath) { - addJavaScriptExtractorDiagnostic( - sourceRoot, - extractorResult.error, - codeqlExePath, - sourceRoot, - ); - } - logExtractorStop(false, 'JavaScript extractor failed'); - } else { - logExtractorStop(true, 'JavaScript extraction completed (CDS processing was skipped)'); - } - - console.log(`Completed run of the cds-extractor.js script for the CDS extractor.`); - process.exit(0); // Graceful exit to skip the rest of the processing } } catch (error) { const errorMessage = `Failed to build CDS dependency graph: ${String(error)}`; cdsExtractorLog('error', errorMessage); - // Add diagnostic for dependency graph build failure if (codeqlExePath) { addDependencyGraphDiagnostic(sourceRoot, errorMessage, codeqlExePath); } - // Continue with a warning instead of exiting - let JavaScript extractor proceed with non-CDS files logExtractorStop( false, 'Warning: Dependency graph build failed, skipping CDS-specific processing', ); - - // Skip the rest of CDS processing and go directly to JavaScript extraction - configureLgtmIndexFilters(); - - // Run CodeQL's JavaScript extractor to process any remaining files - logPerformanceTrackingStart('JavaScript Extraction'); - const extractorResult = runJavaScriptExtractor( + handleEarlyExit( sourceRoot, - autobuildScriptPath || '', // Use empty string if autobuildScriptPath is undefined + autobuildScriptPath || '', codeqlExePath, + 'JavaScript extraction completed (CDS processing was skipped)', ); - logPerformanceTrackingStop('JavaScript Extraction'); - - if (!extractorResult.success && extractorResult.error) { - cdsExtractorLog('error', `Error running JavaScript extractor: ${extractorResult.error}`); - if (codeqlExePath) { - addJavaScriptExtractorDiagnostic( - sourceRoot, - extractorResult.error, - codeqlExePath, - sourceRoot, - ); - } - logExtractorStop(false, 'JavaScript extractor failed'); - } else { - logExtractorStop(true, 'JavaScript extraction completed (CDS processing was skipped)'); - } - - console.log(`Completed run of the cds-extractor.js script for the CDS extractor.`); - process.exit(0); // Graceful exit to skip the rest of the processing } +// Install dependencies logPerformanceTrackingStart('Dependency Installation'); const projectCacheDirMap = cacheInstallDependencies(dependencyGraph, sourceRoot, codeqlExePath); logPerformanceTrackingStop('Dependency Installation'); -// Check if dependency installation resulted in any usable project mappings if (projectCacheDirMap.size === 0) { cdsExtractorLog( 'error', 'No project cache directory mappings were created. This indicates that dependency installation failed for all discovered projects.', ); - // This is a critical error if we have projects but no cache mappings if (dependencyGraph.projects.size > 0) { const errorMessage = `Found ${dependencyGraph.projects.size} CDS projects but failed to install dependencies for any of them. Cannot proceed with compilation.`; cdsExtractorLog('error', errorMessage); - // Add diagnostic for dependency installation failure if (codeqlExePath) { addDependencyInstallationDiagnostic(sourceRoot, errorMessage, codeqlExePath); } - // Continue with a warning instead of exiting - let JavaScript extractor proceed logExtractorStop( false, 'Warning: Dependency installation failed for all projects, continuing with limited functionality', ); } - // If we have no projects and no cache mappings, this should have been caught earlier cdsExtractorLog( 'warn', 'No projects and no cache mappings - this should have been detected earlier.', ); } +// Collect all CDS files to process const cdsFilePathsToProcess: string[] = []; - -// Use the dependency graph to collect all `.cds` files from each project. -// We want to "extract" all `.cds` files from all projects so that we have a copy -// of each `.cds` source file in the CodeQL database. for (const project of dependencyGraph.projects.values()) { cdsFilePathsToProcess.push(...project.cdsFiles); } -// TODO : Improve logging / debugging of dependencyGraph.statusSummary. Just log the JSON? cdsExtractorLog( 'info', `Found ${cdsFilePathsToProcess.length} total CDS files, ${dependencyGraph.statusSummary.totalCdsFiles} CDS files in dependency graph`, ); +// Compile CDS files logPerformanceTrackingStart('CDS Compilation'); try { - // Use the new orchestrated compilation approach (autobuild mode, no debug) orchestrateCompilation(dependencyGraph, projectCacheDirMap, codeqlExePath); - // Handle compilation failures for normal mode if (!dependencyGraph.statusSummary.overallSuccess) { cdsExtractorLog( 'error', `Compilation completed with failures: ${dependencyGraph.statusSummary.failedCompilations} failed out of ${dependencyGraph.statusSummary.totalCompilationTasks} total tasks`, ); - // Add diagnostics for critical errors for (const error of dependencyGraph.errors.critical) { cdsExtractorLog('error', `Critical error in ${error.phase}: ${error.message}`); } - - // Don't exit with error - let the JavaScript extractor run on whatever was compiled } logPerformanceTrackingStop('CDS Compilation'); @@ -320,10 +239,9 @@ try { logPerformanceTrackingStop('CDS Compilation'); cdsExtractorLog('error', `Compilation orchestration failed: ${String(error)}`); - // Add diagnostic for the overall failure if (cdsFilePathsToProcess.length > 0) { addCompilationDiagnostic( - cdsFilePathsToProcess[0], // Use first file as representative + cdsFilePathsToProcess[0], `Compilation orchestration failed: ${String(error)}`, codeqlExePath, sourceRoot, @@ -331,56 +249,22 @@ try { } } -// Configure the "LGTM" index filters for proper extraction. -configureLgtmIndexFilters(); - -// Run CodeQL's JavaScript extractor to process the .cds source files and -// the compiled .cds.json files. -logPerformanceTrackingStart('JavaScript Extraction'); -const extractionStartTime = Date.now(); -const extractorResult = runJavaScriptExtractor(sourceRoot, autobuildScriptPath, codeqlExePath); -const extractionEndTime = Date.now(); -logPerformanceTrackingStop('JavaScript Extraction'); - -// Update the dependency graph's performance metrics with the extraction duration -dependencyGraph.statusSummary.performance.extractionDurationMs = - extractionEndTime - extractionStartTime; - -// Calculate total duration by summing all phases -const totalDuration = - dependencyGraph.statusSummary.performance.parsingDurationMs + - dependencyGraph.statusSummary.performance.compilationDurationMs + - dependencyGraph.statusSummary.performance.extractionDurationMs; -dependencyGraph.statusSummary.performance.totalDurationMs = totalDuration; - -if (!extractorResult.success && extractorResult.error) { - cdsExtractorLog('error', `Error running JavaScript extractor: ${extractorResult.error}`); - - // Add diagnostic for JavaScript extractor failure - if (codeqlExePath && dependencyGraph.projects.size > 0) { - // Use the first CDS file as a representative file for the diagnostic - const firstProject = Array.from(dependencyGraph.projects.values())[0]; - const representativeFile = firstProject.cdsFiles[0] || sourceRoot; - addJavaScriptExtractorDiagnostic( - representativeFile, - extractorResult.error, - codeqlExePath, - sourceRoot, - ); - } +// Run JavaScript extraction with marker file handling +const extractionSuccess = runJavaScriptExtractionWithMarker( + sourceRoot, + autobuildScriptPath, + codeqlExePath, + dependencyGraph, +); - logExtractorStop(false, 'JavaScript extractor failed'); -} else { - logExtractorStop(true, 'CDS extraction completed successfully'); -} +logExtractorStop( + extractionSuccess, + extractionSuccess ? 'CDS extraction completed successfully' : 'JavaScript extractor failed', +); cdsExtractorLog( 'info', 'CDS Extractor Status Report : Final...\n' + generateStatusReport(dependencyGraph), ); -// Use the `cds-extractor.js` name in the log message as that is the name of the script -// that is actually run by the `codeql database index-files` command. This TypeScript -// file is where the code/logic is edited/implemented, but the runnable script is -// generated by the TypeScript compiler and is named `cds-extractor.js`. console.log(`Completed run of the cds-extractor.js script for the CDS extractor.`); diff --git a/extractors/cds/tools/dist/cds-extractor.bundle.js b/extractors/cds/tools/dist/cds-extractor.bundle.js index d1dda3471..63834234b 100644 --- a/extractors/cds/tools/dist/cds-extractor.bundle.js +++ b/extractors/cds/tools/dist/cds-extractor.bundle.js @@ -358,8 +358,11 @@ var parseClass = (glob2, position) => { }; // node_modules/glob/node_modules/minimatch/dist/esm/unescape.js -var unescape = (s, { windowsPathsNoEscape = false } = {}) => { - return windowsPathsNoEscape ? s.replace(/\[([^\/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, "$1$2").replace(/\\([^\/])/g, "$1"); +var unescape = (s, { windowsPathsNoEscape = false, magicalBraces = true } = {}) => { + if (magicalBraces) { + return windowsPathsNoEscape ? s.replace(/\[([^\/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, "$1$2").replace(/\\([^\/])/g, "$1"); + } + return windowsPathsNoEscape ? s.replace(/\[([^\/\\{}])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\{}])\]/g, "$1$2").replace(/\\([^\/{}])/g, "$1"); }; // node_modules/glob/node_modules/minimatch/dist/esm/ast.js @@ -713,7 +716,7 @@ var AST = class _AST { if (this.#root === this) this.#fillNegs(); if (!this.type) { - const noEmpty = this.isStart() && this.isEnd(); + const noEmpty = this.isStart() && this.isEnd() && !this.#parts.some((s) => typeof s !== "string"); const src = this.#parts.map((p) => { const [re, _, hasMagic2, uflag] = typeof p === "string" ? _AST.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot); this.#hasMagic = this.#hasMagic || hasMagic2; @@ -823,10 +826,7 @@ var AST = class _AST { } } if (c === "*") { - if (noEmpty && glob2 === "*") - re += starNoEmpty; - else - re += star; + re += noEmpty && glob2 === "*" ? starNoEmpty : star; hasMagic2 = true; continue; } @@ -842,7 +842,10 @@ var AST = class _AST { }; // node_modules/glob/node_modules/minimatch/dist/esm/escape.js -var escape = (s, { windowsPathsNoEscape = false } = {}) => { +var escape = (s, { windowsPathsNoEscape = false, magicalBraces = false } = {}) => { + if (magicalBraces) { + return windowsPathsNoEscape ? s.replace(/[?*()[\]{}]/g, "[$&]") : s.replace(/[?*()[\]\\{}]/g, "\\$&"); + } return windowsPathsNoEscape ? s.replace(/[?*()[\]]/g, "[$&]") : s.replace(/[?*()[\]\\]/g, "\\$&"); }; @@ -1483,16 +1486,27 @@ var Minimatch = class { pp[i] = twoStar; } } else if (next === void 0) { - pp[i - 1] = prev + "(?:\\/|" + twoStar + ")?"; + pp[i - 1] = prev + "(?:\\/|\\/" + twoStar + ")?"; } else if (next !== GLOBSTAR) { pp[i - 1] = prev + "(?:\\/|\\/" + twoStar + "\\/)" + next; pp[i + 1] = GLOBSTAR; } }); - return pp.filter((p) => p !== GLOBSTAR).join("/"); + const filtered = pp.filter((p) => p !== GLOBSTAR); + if (this.partial && filtered.length >= 1) { + const prefixes = []; + for (let i = 1; i <= filtered.length; i++) { + prefixes.push(filtered.slice(0, i).join("/")); + } + return "(?:" + prefixes.join("|") + ")"; + } + return filtered.join("/"); }).join("|"); const [open, close] = set.length > 1 ? ["(?:", ")"] : ["", ""]; re = "^" + open + re + close + "$"; + if (this.partial) { + re = "^(?:\\/|" + open + re.slice(1, -1) + close + ")$"; + } if (this.negate) re = "^(?!" + re + ").+$"; try { @@ -6634,6 +6648,11 @@ var import_path2 = require("path"); var import_fs2 = require("fs"); var import_path = require("path"); +// src/constants.ts +var modelCdsJsonFile = "model.cds.json"; +var cdsExtractorMarkerFileName = "cds-extractor-marker.js"; +var cdsExtractorMarkerFileContent = '"Placeholder content created by the CDS extractor. This file can be safely deleted.";'; + // src/logging/cdsExtractorLog.ts var sourceRootDirectory; var sessionId = Date.now().toString(); @@ -6691,13 +6710,13 @@ function logExtractorStart(sourceRoot2) { } function logExtractorStop(success = true, additionalSummary) { const endTime = Date.now(); - const totalDuration2 = formatDuration(extractorStartTime, endTime); + const totalDuration = formatDuration(extractorStartTime, endTime); const status = success ? "SUCCESS" : "FAILURE"; if (additionalSummary) { cdsExtractorLog("info", additionalSummary); } cdsExtractorLog("info", `=== CDS EXTRACTOR END [${sessionId}] - ${status} ===`); - cdsExtractorLog("info", `Total Duration: ${totalDuration2}`); + cdsExtractorLog("info", `Total Duration: ${totalDuration}`); } function logPerformanceMilestone(milestone, additionalInfo) { const currentTime = Date.now(); @@ -6824,6 +6843,26 @@ function recursivelyRenameJsonFiles(dirPath) { } } } +function createMarkerFile(sourceRoot2) { + const markerFilePath = (0, import_path.join)(sourceRoot2, cdsExtractorMarkerFileName); + try { + (0, import_fs2.writeFileSync)(markerFilePath, cdsExtractorMarkerFileContent, "utf8"); + cdsExtractorLog("info", `Created marker file: ${markerFilePath}`); + } catch (error) { + cdsExtractorLog("warn", `Failed to create marker file: ${String(error)}`); + } + return markerFilePath; +} +function removeMarkerFile(markerFilePath) { + if ((0, import_fs2.existsSync)(markerFilePath)) { + try { + (0, import_fs2.unlinkSync)(markerFilePath); + cdsExtractorLog("info", `Removed marker file: ${markerFilePath}`); + } catch (error) { + cdsExtractorLog("warn", `Failed to remove marker file: ${String(error)}`); + } + } +} // src/cds/compiler/command.ts var DEFAULT_COMMAND_TIMEOUT_MS = 1e4; @@ -7152,7 +7191,7 @@ function getCdsVersion(cdsCommand, cacheDir) { npm_config_prefix: cacheDir }; } - const result = (0, import_child_process2.spawnSync)(cdsCommand, ["--version"], spawnOptions); + const result = (0, import_child_process2.spawnSync)(`${cdsCommand} --version`, spawnOptions); if (result.status === 0 && result.stdout) { const versionOutput = result.stdout.toString().trim(); const match2 = versionOutput.match(/@sap\/cds[^0-9]*([0-9]+\.[0-9]+\.[0-9]+)/); @@ -7167,9 +7206,6 @@ function getCdsVersion(cdsCommand, cacheDir) { } } -// src/constants.ts -var modelCdsJsonFile = "model.cds.json"; - // src/cds/compiler/compile.ts function parseCommandForSpawn(commandString) { const parts = commandString.trim().split(/\s+/); @@ -9096,44 +9132,10 @@ function buildCdsProjectDependencyGraph(sourceRootDir) { } // src/codeql.ts -var import_child_process8 = require("child_process"); -function runJavaScriptExtractor(sourceRoot2, autobuildScriptPath2, codeqlExePath2) { - cdsExtractorLog( - "info", - `Extracting the .cds.json files by running the 'javascript' extractor autobuild script: - ${autobuildScriptPath2}` - ); - const result = (0, import_child_process8.spawnSync)(autobuildScriptPath2, [], { - cwd: sourceRoot2, - env: process.env, - shell: true, - stdio: "inherit" - }); - if (result.error) { - const errorMessage = `Error running JavaScript extractor: ${result.error.message}`; - if (codeqlExePath2) { - addJavaScriptExtractorDiagnostic(sourceRoot2, errorMessage, codeqlExePath2, sourceRoot2); - } - return { - success: false, - error: errorMessage - }; - } - if (result.status !== 0) { - const errorMessage = `JavaScript extractor failed with exit code ${String(result.status)}`; - if (codeqlExePath2) { - addJavaScriptExtractorDiagnostic(sourceRoot2, errorMessage, codeqlExePath2, sourceRoot2); - } - return { - success: false, - error: errorMessage - }; - } - return { success: true }; -} +var import_child_process9 = require("child_process"); // src/environment.ts -var import_child_process9 = require("child_process"); +var import_child_process8 = require("child_process"); var import_fs7 = require("fs"); var import_os = require("os"); var import_path12 = require("path"); @@ -9170,7 +9172,7 @@ function getCodeQLExePath() { 'CODEQL_DIST environment variable not set or invalid. Attempting to find CodeQL executable via system PATH using "codeql version --format=json".' ); try { - const versionOutput = (0, import_child_process9.execFileSync)(codeqlExeName, ["version", "--format=json"], { + const versionOutput = (0, import_child_process8.execFileSync)(codeqlExeName, ["version", "--format=json"], { encoding: "utf8", timeout: 5e3, // 5 seconds timeout @@ -9235,7 +9237,7 @@ function getJavaScriptExtractorRoot(codeqlExePath2) { return ""; } try { - jsExtractorRoot = (0, import_child_process9.execFileSync)( + jsExtractorRoot = (0, import_child_process8.execFileSync)( codeqlExePath2, ["resolve", "extractor", "--language=javascript"], { stdio: "pipe" } @@ -9289,6 +9291,7 @@ ${process.env.LGTM_INDEX_FILTERS}` (0, import_path12.join)("exclude:**", "*.*"), (0, import_path12.join)("include:**", "*.cds.json"), (0, import_path12.join)("include:**", "*.cds"), + (0, import_path12.join)("include:**", cdsExtractorMarkerFileName), (0, import_path12.join)("exclude:**", "node_modules", "**", "*.*") ].join("\n"); process.env.LGTM_INDEX_FILTERS = lgtmIndexFiltersPatterns + excludeFilters; @@ -9336,6 +9339,83 @@ function setupAndValidateEnvironment(sourceRoot2) { }; } +// src/codeql.ts +function runJavaScriptExtractor(sourceRoot2, autobuildScriptPath2, codeqlExePath2) { + cdsExtractorLog( + "info", + `Extracting the .cds.json files by running the 'javascript' extractor autobuild script: + ${autobuildScriptPath2}` + ); + const result = (0, import_child_process9.spawnSync)(autobuildScriptPath2, { + cwd: sourceRoot2, + env: process.env, + shell: true, + stdio: "inherit" + }); + if (result.error) { + const errorMessage = `Error running JavaScript extractor: ${result.error.message}`; + if (codeqlExePath2) { + addJavaScriptExtractorDiagnostic(sourceRoot2, errorMessage, codeqlExePath2, sourceRoot2); + } + return { + success: false, + error: errorMessage + }; + } + if (result.status !== 0) { + const errorMessage = `JavaScript extractor failed with exit code ${String(result.status)}`; + if (codeqlExePath2) { + addJavaScriptExtractorDiagnostic(sourceRoot2, errorMessage, codeqlExePath2, sourceRoot2); + } + return { + success: false, + error: errorMessage + }; + } + return { success: true }; +} +function runJavaScriptExtractionWithMarker(sourceRoot2, autobuildScriptPath2, codeqlExePath2, dependencyGraph2) { + configureLgtmIndexFilters(); + const markerFilePath = createMarkerFile(sourceRoot2); + try { + logPerformanceTrackingStart("JavaScript Extraction"); + const extractionStartTime = Date.now(); + const extractorResult = runJavaScriptExtractor(sourceRoot2, autobuildScriptPath2, codeqlExePath2); + const extractionEndTime = Date.now(); + logPerformanceTrackingStop("JavaScript Extraction"); + if (dependencyGraph2) { + dependencyGraph2.statusSummary.performance.extractionDurationMs = extractionEndTime - extractionStartTime; + dependencyGraph2.statusSummary.performance.totalDurationMs = dependencyGraph2.statusSummary.performance.parsingDurationMs + dependencyGraph2.statusSummary.performance.compilationDurationMs + dependencyGraph2.statusSummary.performance.extractionDurationMs; + } + if (!extractorResult.success && extractorResult.error) { + cdsExtractorLog("error", `Error running JavaScript extractor: ${extractorResult.error}`); + if (codeqlExePath2) { + let representativeFile = sourceRoot2; + if (dependencyGraph2 && dependencyGraph2.projects.size > 0) { + const firstProject = Array.from(dependencyGraph2.projects.values())[0]; + representativeFile = firstProject.cdsFiles[0] ?? sourceRoot2; + } + addJavaScriptExtractorDiagnostic( + representativeFile, + extractorResult.error, + codeqlExePath2, + sourceRoot2 + ); + } + return false; + } + return true; + } finally { + removeMarkerFile(markerFilePath); + } +} +function handleEarlyExit(sourceRoot2, autobuildScriptPath2, codeqlExePath2, skipMessage) { + const success = runJavaScriptExtractionWithMarker(sourceRoot2, autobuildScriptPath2, codeqlExePath2); + logExtractorStop(success, success ? skipMessage : "JavaScript extractor failed"); + console.log(`Completed run of the cds-extractor.js script for the CDS extractor.`); + process.exit(0); +} + // src/utils.ts var import_path13 = require("path"); var USAGE_MESSAGE = ` Usage: node