Skip to content

Commit 8591f83

Browse files
invalidclaude
andcommitted
fix: unify .h reclassification between scan and update, fix stale JSDoc and redundant hash
- Extract hasCppSourceFiles() and effectiveLanguage() to traverser.js so both scanner.js and update command share the same .h → cpp logic - Update query.js JSDoc to reference current field names (fileImports/importedBy) - Remove redundant hash recomputation in update command Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e982af7 commit 8591f83

4 files changed

Lines changed: 33 additions & 12 deletions

File tree

cli/src/commands/update.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import path from 'path';
22
import fs from 'fs/promises';
33
import { loadGraph, loadMeta, saveGraph, computeFileHash, getGitCommitHash, isEntryPoint } from '../graph.js';
4-
import { traverseFiles, detectLanguage } from '../traverser.js';
4+
import { traverseFiles, detectLanguage, hasCppSourceFiles, effectiveLanguage } from '../traverser.js';
55
import { initParser, parseFile } from '../parser.js';
66
import { detectModuleName } from '../scanner.js';
77
import { detectChangedFiles, mergeGraphUpdate } from '../differ.js';
@@ -37,6 +37,7 @@ export function registerUpdateCommand(program) {
3737

3838
// Step 3: Traverse files and compute current hashes
3939
const files = await traverseFiles(rootDir);
40+
const hasCpp = hasCppSourceFiles(files);
4041
const currentHashes = {};
4142

4243
for (const absPath of files) {
@@ -66,17 +67,20 @@ export function registerUpdateCommand(program) {
6667

6768
for (const relPath of changedPaths) {
6869
const absPath = path.resolve(rootDir, relPath);
69-
const language = detectLanguage(absPath);
70+
let language = detectLanguage(absPath);
7071
if (!language) continue;
7172

73+
// Reclassify .h files as C++ when the project contains C++ sources
74+
language = effectiveLanguage(absPath, language, hasCpp);
75+
7276
let content;
7377
try {
7478
content = await fs.readFile(absPath, 'utf-8');
7579
} catch {
7680
continue;
7781
}
7882

79-
const hash = computeFileHash(content);
83+
const hash = currentHashes[relPath];
8084

8185
let parsed;
8286
try {

cli/src/query.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* @param {string} symbolName - The name to search for (case-sensitive substring match).
1313
* @param {object} [options] - Optional filters.
1414
* @param {'function'|'class'|'type'} [options.type] - Restrict search to a specific kind.
15-
* @returns {Array<{kind: string, name: string, signature?: string, file: string, module: string, lines: {start: number, end: number}, calls: string[], calledBy: string[]}>}
15+
* @returns {Array<{kind: string, name: string, signature?: string, file: string, module: string, lines: {start: number, end: number}, fileImports: string[], importedBy: string[]}>}
1616
*/
1717
export function querySymbol(graph, symbolName, options = {}) {
1818
const results = [];

cli/src/scanner.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import path from 'path';
22
import fs from 'fs/promises';
3-
import { traverseFiles, detectLanguage } from './traverser.js';
3+
import { traverseFiles, detectLanguage, hasCppSourceFiles, effectiveLanguage } from './traverser.js';
44
import { initParser, parseFile } from './parser.js';
55
import { createEmptyGraph, computeFileHash, isEntryPoint } from './graph.js';
66

@@ -54,10 +54,7 @@ export async function scanProject(rootDir, options = {}) {
5454
const files = await traverseFiles(rootDir, { exclude: options.exclude || [] });
5555

5656
// Detect whether the project contains C++ files, so we can treat .h as C++
57-
const hasCppFiles = files.some(f => {
58-
const ext = path.extname(f).toLowerCase();
59-
return ['.cpp', '.cc', '.cxx', '.hpp', '.hh'].includes(ext);
60-
});
57+
const hasCppFiles = hasCppSourceFiles(files);
6158

6259
// Index: absolute path (normalised with forward slashes) → parsed data + module
6360
const fileIndex = new Map();
@@ -72,9 +69,7 @@ export async function scanProject(rootDir, options = {}) {
7269
if (!language) continue;
7370

7471
// Reclassify .h files as C++ when the project contains C++ sources
75-
if (language === 'c' && hasCppFiles && path.extname(absPath).toLowerCase() === '.h') {
76-
language = 'cpp';
77-
}
72+
language = effectiveLanguage(absPath, language, hasCppFiles);
7873

7974
let content;
8075
try {

cli/src/traverser.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,26 @@ export async function traverseFiles(rootDir, options = {}) {
4848
return files.sort();
4949
}
5050

51+
/** C++ file extensions (excluding .h which is shared with C). */
52+
const CPP_EXTENSIONS = new Set(['.cpp', '.cc', '.cxx', '.hpp', '.hh']);
53+
54+
/**
55+
* Check whether a list of absolute file paths contains any C++ source files.
56+
* Used to decide if `.h` headers should be reclassified as C++.
57+
*/
58+
export function hasCppSourceFiles(files) {
59+
return files.some(f => CPP_EXTENSIONS.has(path.extname(f).toLowerCase()));
60+
}
61+
62+
/**
63+
* Return the effective language for a file, applying `.h` → `cpp`
64+
* reclassification when the project contains C++ sources.
65+
*/
66+
export function effectiveLanguage(filePath, baseLanguage, projectHasCpp) {
67+
if (baseLanguage === 'c' && projectHasCpp && path.extname(filePath).toLowerCase() === '.h') {
68+
return 'cpp';
69+
}
70+
return baseLanguage;
71+
}
72+
5173
export { LANGUAGE_EXTENSIONS, ALL_EXTENSIONS };

0 commit comments

Comments
 (0)