Skip to content

Commit d4dd37a

Browse files
committed
Refactor CDS extractor run modes
Remove "run modes" in an attempt to simplify the overall CDS extractor.
1 parent 359290e commit d4dd37a

22 files changed

Lines changed: 7925 additions & 1396 deletions

extractors/cds/tools/.gitignore

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,3 @@ debug/
88
# local environment.
99
out/
1010

11-
# Since we expect the build process to be run on the system where the CDS extractor
12-
# is being run, we do not need/want to check-in our own package-lock.json version
13-
# when we know it will be different / overwritten on each system.
14-
package-lock.json
15-

extractors/cds/tools/cds-extractor.ts

Lines changed: 38 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,46 @@ import { join } from 'path';
33
import { sync as globSync } from 'glob';
44

55
import { determineCdsCommand } from './src/cds';
6-
import { orchestrateCompilation } from './src/cds/compiler/graph';
7-
import {
8-
handleDebugParserMode,
9-
handleDebugCompilerMode,
10-
isDebugMode,
11-
isDebugParserMode,
12-
isDebugCompilerMode,
13-
} from './src/cds/parser/debugUtils';
14-
import { buildEnhancedCdsProjectDependencyGraph } from './src/cds/parser/graph';
6+
import { orchestrateCompilation } from './src/cds/compiler';
7+
import { buildEnhancedCdsProjectDependencyGraph } from './src/cds/parser';
158
import { runJavaScriptExtractor } from './src/codeql';
169
import { addCompilationDiagnostic } from './src/diagnostics';
1710
import { configureLgtmIndexFilters, setupAndValidateEnvironment } from './src/environment';
1811
import {
1912
cdsExtractorLog,
20-
setSourceRootDirectory,
13+
endPerformanceTracking,
14+
logExtractorStop,
2115
logExtractorStart,
22-
logExtractorEnd,
16+
logMemoryUsage,
2317
logPerformanceMilestone,
18+
setSourceRootDirectory,
2419
startPerformanceTracking,
25-
endPerformanceTracking,
26-
logMemoryUsage,
2720
} from './src/logging';
2821
import { installDependencies } from './src/packageManager';
29-
import { RunMode } from './src/runMode';
3022
import { validateArguments } from './src/utils';
3123

32-
// Validate the first argument matches an allowed run mode and validate that
33-
// the total number of arguments is correct for the specified run mode.
24+
// Validate the script arguments.
3425
const validationResult = validateArguments(process.argv);
3526
if (!validationResult.isValid) {
3627
console.warn(validationResult.usageMessage);
3728
// Exit with an error code on invalid use of this script.
3829
process.exit(1);
3930
}
4031

41-
// Get the validated and sanitized arguments
42-
const { runMode, sourceRoot } = validationResult.args!;
32+
// Get the validated and sanitized arguments.
33+
const { sourceRoot } = validationResult.args!;
4334

44-
// Initialize the unified logging system with the source root directory
35+
// Initialize the unified logging system with the source root directory.
4536
setSourceRootDirectory(sourceRoot);
4637

47-
// Log the start of the CDS extractor session
48-
logExtractorStart(runMode, sourceRoot);
38+
// Log the start of the CDS extractor session as a whole.
39+
logExtractorStart(sourceRoot);
40+
// We log the memory usage at the start of the extractor to track memory growth.
4941
logMemoryUsage('Extractor Start');
5042

51-
// Check for autobuild mode
52-
if (runMode === (RunMode.AUTOBUILD as string)) {
53-
cdsExtractorLog('info', 'Autobuild mode is not implemented yet.');
54-
logExtractorEnd(false, 'Terminated: Autobuild mode not implemented');
55-
process.exit(1);
56-
}
57-
58-
// Setup the environment and validate all requirements first, before changing directory
59-
// This ensures we can properly locate the CodeQL tools
43+
// Setup the environment and validate all requirements first, before changing
44+
// directory back to the "sourceRoot" directory. This ensures we can properly locate
45+
// the CodeQL tools.
6046
startPerformanceTracking('Environment Setup');
6147
const {
6248
success: envSetupSuccess,
@@ -76,7 +62,7 @@ if (!envSetupSuccess) {
7662
)}.`,
7763
);
7864
// Exit with an error code when environment setup fails.
79-
logExtractorEnd(false, 'Terminated: Environment setup failed');
65+
logExtractorStop(false, 'Terminated: Environment setup failed');
8066
process.exit(1);
8167
}
8268

@@ -86,18 +72,24 @@ process.chdir(sourceRoot);
8672

8773
cdsExtractorLog(
8874
'info',
89-
`CodeQL CDS extractor using run mode '${runMode}' for scan of project source root directory '${sourceRoot}'.`,
75+
`CodeQL CDS extractor using autobuild mode for scan of project source root directory '${sourceRoot}'.`,
9076
);
9177

92-
// Using the enhanced project-aware approach to find CDS projects and their dependencies
9378
cdsExtractorLog('info', 'Building enhanced CDS project dependency graph...');
9479

95-
// Build the enhanced dependency graph using the new enhanced parser
80+
// Build the CDS project `dependencyGraph` as the foundation for the extraction process.
81+
// This graph will contain all discovered CDS projects, their dependencies, the `.cds`
82+
// files discovered within each project, the expected `.cds.json` files for each project
83+
// and the compilation status of such `.cds.json` files.
84+
//
85+
// The `dependencyGraph` will be updated as CDS extractor phases progress, allowing for
86+
// a single data structure to be used for planning, execution, retries (i.e. error handling),
87+
// debugging, and final reporting.
9688
let dependencyGraph;
9789

98-
startPerformanceTracking('Dependency Graph Build');
9990
try {
100-
dependencyGraph = buildEnhancedCdsProjectDependencyGraph(sourceRoot, runMode, __dirname);
91+
startPerformanceTracking('Dependency Graph Build');
92+
dependencyGraph = buildEnhancedCdsProjectDependencyGraph(sourceRoot, __dirname);
10193
endPerformanceTracking('Dependency Graph Build');
10294

10395
logPerformanceMilestone(
@@ -106,13 +98,6 @@ try {
10698
);
10799
logMemoryUsage('After Dependency Graph');
108100

109-
// Handle debug modes early - these modes should exit after completing their specific tasks
110-
if (isDebugParserMode(runMode)) {
111-
const debugSuccess = handleDebugParserMode(dependencyGraph, sourceRoot, __dirname);
112-
logExtractorEnd(debugSuccess, `Debug parser mode completed: ${runMode}`);
113-
process.exit(debugSuccess ? 0 : 1);
114-
}
115-
116101
// Log details about discovered projects for debugging
117102
if (dependencyGraph.projects.size > 0) {
118103
for (const [projectDir, project] of dependencyGraph.projects.entries()) {
@@ -152,40 +137,25 @@ try {
152137
} catch (error) {
153138
cdsExtractorLog('error', `Failed to build enhanced dependency graph: ${String(error)}`);
154139
// Exit with error since we can't continue without a proper dependency graph
155-
logExtractorEnd(false, 'Terminated: Dependency graph build failed');
140+
logExtractorStop(false, 'Terminated: Dependency graph build failed');
156141
process.exit(1);
157142
}
158143

159-
// Install dependencies of discovered CAP/CDS projects
160-
cdsExtractorLog('info', 'Installing dependencies for discovered CDS projects...');
161-
162144
startPerformanceTracking('Dependency Installation');
163145
const projectCacheDirMap = installDependencies(dependencyGraph, sourceRoot, codeqlExePath);
164146
endPerformanceTracking('Dependency Installation');
165147

166148
const cdsFilePathsToProcess: string[] = [];
167149

168-
cdsExtractorLog('info', 'Extracting CDS files from discovered projects...');
169-
170150
// Use the enhanced dependency graph to collect all `.cds` files from each project.
171151
// We want to "extract" all `.cds` files from all projects so that we have a copy
172152
// of each `.cds` source file in the CodeQL database.
173153
for (const project of dependencyGraph.projects.values()) {
174154
cdsFilePathsToProcess.push(...project.cdsFiles);
175155
}
176156

177-
cdsExtractorLog('info', 'Processing CDS files to JSON using enhanced compilation orchestration...');
178-
179-
// Check if we're running in debug mode
180-
if (isDebugMode(runMode)) {
181-
cdsExtractorLog(
182-
'info',
183-
`Running in ${runMode} mode - enhanced debug information will be collected...`,
184-
);
185-
}
186-
187-
// Initialize CDS command cache early to avoid repeated testing during compilation
188-
// This is a critical optimization that avoids testing commands for every single file
157+
// Initialize CDS command cache early to avoid repeated testing during compilation.
158+
// This is a critical optimization that avoids testing commands for every single file.
189159
startPerformanceTracking('CDS Command Cache Initialization');
190160
try {
191161
determineCdsCommand(undefined, sourceRoot);
@@ -194,25 +164,18 @@ try {
194164
} catch (error) {
195165
endPerformanceTracking('CDS Command Cache Initialization');
196166
cdsExtractorLog('warn', `CDS command cache initialization failed: ${String(error)}`);
197-
// Continue anyway - individual calls will handle fallbacks
198167
}
199168

169+
// TODO : Improve logging / debugging of dependencyGraph.statusSummary. Just log the JSON?
200170
cdsExtractorLog(
201171
'info',
202172
`Found ${cdsFilePathsToProcess.length} total CDS files, ${dependencyGraph.statusSummary.totalCdsFiles} CDS files in dependency graph`,
203173
);
204174

205175
startPerformanceTracking('CDS Compilation');
206176
try {
207-
// Use the new orchestrated compilation approach with debug awareness
208-
orchestrateCompilation(dependencyGraph, projectCacheDirMap, codeqlExePath, isDebugMode(runMode));
209-
210-
// Check if we should exit for debug modes after successful compilation
211-
if (isDebugCompilerMode(runMode)) {
212-
const debugSuccess = handleDebugCompilerMode(dependencyGraph, runMode);
213-
logExtractorEnd(debugSuccess, `Debug mode completed: ${runMode}`);
214-
process.exit(debugSuccess ? 0 : 1);
215-
}
177+
// Use the new orchestrated compilation approach (autobuild mode, no debug)
178+
orchestrateCompilation(dependencyGraph, projectCacheDirMap, codeqlExePath, false);
216179

217180
// Handle compilation failures for normal mode
218181
if (!dependencyGraph.statusSummary.overallSuccess) {
@@ -249,16 +212,17 @@ try {
249212
// Configure the "LGTM" index filters for proper extraction.
250213
configureLgtmIndexFilters();
251214

252-
// Run CodeQL's JavaScript extractor to process the compiled JSON files.
215+
// Run CodeQL's JavaScript extractor to process the .cds source files and
216+
// the compiled .cds.json files.
253217
startPerformanceTracking('JavaScript Extraction');
254218
const extractorResult = runJavaScriptExtractor(sourceRoot, autobuildScriptPath, codeqlExePath);
255219
endPerformanceTracking('JavaScript Extraction');
256220

257221
if (!extractorResult.success && extractorResult.error) {
258222
cdsExtractorLog('error', `Error running JavaScript extractor: ${extractorResult.error}`);
259-
logExtractorEnd(false, 'JavaScript extractor failed');
223+
logExtractorStop(false, 'JavaScript extractor failed');
260224
} else {
261-
logExtractorEnd(true, 'CDS extraction completed successfully');
225+
logExtractorStop(true, 'CDS extraction completed successfully');
262226
}
263227

264228
// Use the `cds-extractor.js` name in the log message as that is the name of the script

extractors/cds/tools/index-files.sh

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,50 @@
22

33
set -eu
44

5-
if [ $# -ne 1 ]
6-
then
7-
echo "Usage: $0 <response_file_path>"
8-
exit 1
9-
fi
5+
## This script currently:
6+
## - ignores any arguments passed to it;
7+
## - assumes it is run from the root of the project source directory;
8+
##
109

1110
if ! command -v node > /dev/null
1211
then
1312
echo "node executable is required (in PATH) to run the 'cds-extractor.js' script. Please install Node.js and try again."
1413
exit 2
1514
fi
1615

17-
if ! command -v npm > /dev/null
18-
then
19-
echo "npm executable is required (in PATH) to install the dependencies for the 'cds-extractor.js' script."
20-
exit 3
21-
fi
22-
2316
# Set the _cwd variable to the present working directory (PWD) as the directory
2417
# from which this script was called, which we assume is the "source root" directory
2518
# of the project that to be scanned / indexed.
2619
_cwd="$PWD"
27-
_response_file_path="$1"
28-
_run_mode="index-files"
2920
_script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
21+
_cds_extractor_js_path="${_script_dir}/out/cds-extractor.js"
22+
_cds_extractor_node_modules_dir="${_script_dir}/node_modules"
3023

31-
echo "Checking response file for CDS files to index"
24+
if [ ! -f "${_cds_extractor_js_path}" ]; then
25+
echo "Error: The 'cds-extractor.js' script does not exist at the expected path: ${_cds_extractor_js_path}"
26+
echo "Please ensure that the script has been built and is available in the 'out' directory."
27+
exit 3
28+
fi
3229

33-
# Terminate early if the _response_file_path doesn't exist or is empty,
34-
# which indicates that no CDS files were selected or found.
35-
if [ ! -f "$_response_file_path" ] || [ ! -s "$_response_file_path" ]
36-
then
37-
echo "'codeql database cds-extractor --language cds' command terminated early as response file '$_response_file_path' does not exist or is empty. This is because no CDS files were selected or found."
38-
# Exit without error to avoid failing any calling (javascript)
39-
# extractor, and llow the tool the report the lack of coverage
40-
# for CDS files.
41-
exit 0
30+
if [ ! -d "${_cds_extractor_node_modules_dir}" ]; then
31+
echo "Error: The 'node_modules' directory does not exist at the expected path: ${_cds_extractor_node_modules_dir}"
32+
echo "Please ensure that the dependencies have been installed by running 'npm install' in the 'extractors/cds/tools' directory."
33+
exit 4
4234
fi
4335

44-
# Change to the directory of this script to ensure that npm looks up the
36+
# Change to the directory of this shell script to ensure that npm looks up the
4537
# package.json file in the correct directory and installs the dependencies
4638
# (i.e. node_modules) relative to this directory. This is technically a
4739
# violation of the assumption that extractor scripts will be run with the
4840
# current working directory set to the root of the project source, but we
4941
# also need node_modules to be installed here and not in the project source
5042
# root, so we make a compromise of:
51-
# 1. changing to this script's directory;
52-
# 2. installing node dependencies here;
53-
# 3. passing the original working directory as a parameter to the
43+
# 1. changing to this shell script's directory;
44+
# 2. passing the original working directory as a parameter to the
5445
# cds-extractor.js script;
55-
# 4. expecting the cds-extractor.js script to immediately change back to
46+
# 3. expecting the cds-extractor.js script to immediately change back to
5647
# original working (aka the project source root) directory.
5748

5849
cd "$_script_dir" && \
59-
echo "Installing node package dependencies" && \
60-
npm install --quiet --no-audit --no-fund && \
61-
echo "Building TypeScript code" && \
62-
npm run build && \
6350
echo "Running the 'cds-extractor.js' script" && \
64-
node "$(dirname "$0")/out/cds-extractor.js" "$_run_mode" "$_cwd" "$_response_file_path"
51+
node "${_cds_extractor_js_path}" "$_cwd"

0 commit comments

Comments
 (0)