Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
},
"linter": {
"rules": {
"recommended": true
"recommended": true,
"style": {
"noNonNullAssertion": "off"
},
"suspicious": {
"noExplicitAny": "off"
}
}
},
"javascript": {
Expand Down
24 changes: 17 additions & 7 deletions scripts/build-wasm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,27 @@ const grammars = [
{ name: 'tree-sitter-php', pkg: 'tree-sitter-php', sub: 'php' },
];

let failed = 0;
for (const g of grammars) {
const pkgDir = dirname(require.resolve(`${g.pkg}/package.json`));
const grammarDir = g.sub ? resolve(pkgDir, g.sub) : pkgDir;

console.log(`Building ${g.name}.wasm from ${grammarDir}...`);
execFileSync('npx', ['tree-sitter', 'build', '--wasm', grammarDir], {
cwd: grammarsDir,
stdio: 'inherit',
shell: true,
});
console.log(` Done: ${g.name}.wasm`);
try {
execFileSync('npx', ['tree-sitter', 'build', '--wasm', grammarDir], {
cwd: grammarsDir,
stdio: 'inherit',
shell: true,
});
console.log(` Done: ${g.name}.wasm`);
} catch (err: any) {
failed++;
console.warn(` WARN: Failed to build ${g.name}.wasm — ${err.message ?? 'unknown error'}`);
}
}

console.log('\nAll grammars built successfully into grammars/');
if (failed > 0) {
console.warn(`\n${failed}/${grammars.length} grammars failed to build (non-fatal — native engine available)`);
} else {
console.log('\nAll grammars built successfully into grammars/');
}
12 changes: 3 additions & 9 deletions src/ast-analysis/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ function setupVisitors(
walkerOpts.getFunctionName = (node: TreeSitterNode): string | null => {
const nameNode = node.childForFieldName('name');
if (nameNode) return nameNode.text;
// biome-ignore lint/suspicious/noExplicitAny: DataflowRulesConfig is structurally compatible at runtime
if (dfRules) return getFuncName(node, dfRules as any);
return null;
};
Expand Down Expand Up @@ -260,8 +259,7 @@ function setupVisitors(
// ─── Result storage helpers ─────────────────────────────────────────────

function storeComplexityResults(results: WalkResults, defs: Definition[], langId: string): void {
// biome-ignore lint/complexity/useLiteralKeys: bracket notation required by noPropertyAccessFromIndexSignature
const complexityResults = (results['complexity'] || []) as ComplexityFuncResult[];
const complexityResults = (results.complexity || []) as ComplexityFuncResult[];
const resultByLine = new Map<number, ComplexityFuncResult[]>();
for (const r of complexityResults) {
if (r.funcNode) {
Expand Down Expand Up @@ -302,8 +300,7 @@ function storeComplexityResults(results: WalkResults, defs: Definition[], langId
}

function storeCfgResults(results: WalkResults, defs: Definition[]): void {
// biome-ignore lint/complexity/useLiteralKeys: bracket notation required by noPropertyAccessFromIndexSignature
const cfgResults = (results['cfg'] || []) as CfgFuncResult[];
const cfgResults = (results.cfg || []) as CfgFuncResult[];
const cfgByLine = new Map<number, CfgFuncResult[]>();
for (const r of cfgResults) {
if (r.funcNode) {
Expand Down Expand Up @@ -362,7 +359,6 @@ async function delegateToBuildFunctions(
const t0 = performance.now();
try {
const { buildAstNodes } = await import('../features/ast.js');
// biome-ignore lint/suspicious/noExplicitAny: ExtractorOutput is a superset of the local FileSymbols expected by buildAstNodes
await buildAstNodes(db, fileSymbols as Map<string, any>, rootDir, engineOpts);
} catch (err: unknown) {
debug(`buildAstNodes failed: ${(err as Error).message}`);
Expand All @@ -374,7 +370,6 @@ async function delegateToBuildFunctions(
const t0 = performance.now();
try {
const { buildComplexityMetrics } = await import('../features/complexity.js');
// biome-ignore lint/suspicious/noExplicitAny: ExtractorOutput is a superset of the local FileSymbols expected by buildComplexityMetrics
await buildComplexityMetrics(db, fileSymbols as Map<string, any>, rootDir, engineOpts);
} catch (err: unknown) {
debug(`buildComplexityMetrics failed: ${(err as Error).message}`);
Expand Down Expand Up @@ -453,8 +448,7 @@ export async function runAnalyses(

if (complexityVisitor) storeComplexityResults(results, defs, langId);
if (cfgVisitor) storeCfgResults(results, defs);
// biome-ignore lint/complexity/useLiteralKeys: bracket notation required by noPropertyAccessFromIndexSignature
if (dataflowVisitor) symbols.dataflow = results['dataflow'] as DataflowResult;
if (dataflowVisitor) symbols.dataflow = results.dataflow as DataflowResult;
}

timing._unifiedWalkMs = performance.now() - t0walk;
Expand Down
1 change: 0 additions & 1 deletion src/ast-analysis/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ export function findFunctionNode(
}

for (let i = 0; i < node.childCount; i++) {
// biome-ignore lint/style/noNonNullAssertion: tree-sitter child(i) within childCount is always non-null
search(node.child(i)!);
}
}
Expand Down
1 change: 0 additions & 1 deletion src/ast-analysis/visitors/cfg-shared.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { TreeSitterNode } from '../../types.js';

// biome-ignore lint/suspicious/noExplicitAny: CFG rules are opaque language-specific objects
export type AnyRules = any;

/** Callback type for the mutual recursion with processStatements in cfg-visitor. */
Expand Down
1 change: 0 additions & 1 deletion src/ast-analysis/visitors/complexity-visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
computeMaintainabilityIndex,
} from '../metrics.js';

// biome-ignore lint/suspicious/noExplicitAny: complexity/halstead rules are opaque language-specific objects
type AnyRules = any;

interface ComplexityAcc {
Expand Down
1 change: 0 additions & 1 deletion src/ast-analysis/visitors/dataflow-visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
truncate,
} from '../visitor-utils.js';

// biome-ignore lint/suspicious/noExplicitAny: dataflow rules are opaque language-specific objects
type AnyRules = any;

interface ScopeEntry {
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/branch-compare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const command: CommandDefinition = {
async execute([base, target], opts, ctx) {
const { branchCompare } = await import('../../presentation/branch-compare.js');
await branchCompare(base!, target!, {
engine: ctx.program.opts()['engine'],
engine: ctx.program.opts().engine,
depth: parseInt(opts.depth as string, 10),
noTests: ctx.resolveNoTests(opts),
json: opts.json,
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const command: CommandDefinition = {
],
async execute([dir], opts, ctx) {
const root = path.resolve(dir || '.');
const engine = ctx.program.opts()['engine'];
const engine = ctx.program.opts().engine;
await buildGraph(root, {
incremental: opts.incremental as boolean,
ast: opts.ast as boolean,
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const command: CommandDefinition = {
);
const { getActiveEngine } = await import('../../domain/parser.js');

const engine = ctx.program.opts()['engine'];
const engine = ctx.program.opts().engine;
const { name: activeName, version: activeVersion } = getActiveEngine({ engine });
const nativeAvailable = isNativeAvailable();

Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const command: CommandDefinition = {
description: 'Watch project for file changes and incrementally update the graph',
async execute([dir], _opts, ctx) {
const root = path.resolve(dir || '.');
const engine = ctx.program.opts()['engine'];
const engine = ctx.program.opts().engine;
await watchProject(root, { engine });
},
};
4 changes: 2 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ program
.option('--engine <engine>', 'Parser engine: native, wasm, or auto (default: auto)', 'auto')
.hook('preAction', (thisCommand) => {
const opts = thisCommand.opts();
if (opts['verbose']) setVerbose(true);
if (opts.verbose) setVerbose(true);
})
.hook('postAction', async (_thisCommand, actionCommand) => {
const name = actionCommand.name();
if (name === 'mcp' || name === 'watch') return;
if (actionCommand.opts()['json']) return;
if (actionCommand.opts().json) return;
try {
const result = await checkForUpdates(pkg.version);
if (result) printUpdateNotification(result.current, result.latest);
Expand Down
2 changes: 1 addition & 1 deletion src/cli/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface CommandDefinition {
description: string;
queryOpts?: boolean;
options?: Array<[string, string, ...unknown[]]>;
validate?(args: string[], opts: CommandOpts, ctx: CliContext): string | void;
validate?(args: string[], opts: CommandOpts, ctx: CliContext): string | undefined;
execute?(args: string[], opts: CommandOpts, ctx: CliContext): void | Promise<void>;
subcommands?: CommandDefinition[];
}
1 change: 0 additions & 1 deletion src/domain/analysis/brief.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ function countTransitiveImporters(
export function briefData(
file: string,
customDbPath: string,
// biome-ignore lint/suspicious/noExplicitAny: config shape is dynamic
opts: { noTests?: boolean; config?: any } = {},
) {
const db = openReadonlyOrFail(customDbPath);
Expand Down
8 changes: 2 additions & 6 deletions src/domain/analysis/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,6 @@ function explainFunctionImpl(
});
}

// biome-ignore lint/suspicious/noExplicitAny: explainFunctionImpl results have dynamic shape with _depth
function explainCallees(
parentResults: any[],
currentDepth: number,
Expand All @@ -405,8 +404,8 @@ function explainCallees(
);
const exact = calleeResults.find((cr) => cr.file === callee.file && cr.line === callee.line);
if (exact) {
(exact as Record<string, unknown>)['_depth'] =
(((r as Record<string, unknown>)['_depth'] as number) || 0) + 1;
(exact as Record<string, unknown>)._depth =
(((r as Record<string, unknown>)._depth as number) || 0) + 1;
newCallees.push(exact);
}
}
Expand All @@ -431,7 +430,6 @@ export function contextData(
kind?: string;
limit?: number;
offset?: number;
// biome-ignore lint/suspicious/noExplicitAny: config shape is dynamic
config?: any;
} = {},
) {
Expand Down Expand Up @@ -509,7 +507,6 @@ export function explainData(
depth?: number;
limit?: number;
offset?: number;
// biome-ignore lint/suspicious/noExplicitAny: config shape is dynamic
config?: any;
} = {},
) {
Expand All @@ -533,7 +530,6 @@ export function explainData(
: explainFunctionImpl(db, target, noTests, getFileLines, displayOpts);

if (kind === 'function' && depth > 0 && results.length > 0) {
// biome-ignore lint/suspicious/noExplicitAny: results are function results when kind === 'function'
const visited = new Set(results.map((r: any) => `${r.name}:${r.file}:${r.line ?? ''}`));
explainCallees(results, depth, visited, db, noTests, getFileLines, displayOpts);
}
Expand Down
2 changes: 0 additions & 2 deletions src/domain/analysis/diff-impact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ function checkBoundaryViolations(
db: BetterSqlite3Database,
changedRanges: Map<string, unknown>,
noTests: boolean,
// biome-ignore lint/suspicious/noExplicitAny: opts shape varies by caller
opts: any,
repoRoot: string,
) {
Expand Down Expand Up @@ -266,7 +265,6 @@ export function diffImpactData(
includeImplementors?: boolean;
limit?: number;
offset?: number;
// biome-ignore lint/suspicious/noExplicitAny: config shape is dynamic
config?: any;
} = {},
) {
Expand Down
2 changes: 0 additions & 2 deletions src/domain/analysis/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export function exportsData(
unused?: boolean;
limit?: number;
offset?: number;
// biome-ignore lint/suspicious/noExplicitAny: config shape is dynamic
config?: any;
} = {},
) {
Expand Down Expand Up @@ -84,7 +83,6 @@ export function exportsData(
totalReexported: first.totalReexported,
totalReexportedUnused: first.totalReexportedUnused,
};
// biome-ignore lint/suspicious/noExplicitAny: paginateResult returns dynamic shape
const paginated: any = paginateResult(base, 'results', {
limit: opts.limit,
offset: opts.offset,
Expand Down
1 change: 0 additions & 1 deletion src/domain/analysis/fn-impact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ export function fnImpactData(
includeImplementors?: boolean;
limit?: number;
offset?: number;
// biome-ignore lint/suspicious/noExplicitAny: config shape is dynamic
config?: any;
} = {},
) {
Expand Down
6 changes: 1 addition & 5 deletions src/domain/analysis/module-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,11 +380,7 @@ export function moduleMapData(customDbPath: string, limit = 20, opts: { noTests?
}
}

export function statsData(
customDbPath: string,
// biome-ignore lint/suspicious/noExplicitAny: config shape is dynamic
opts: { noTests?: boolean; config?: any } = {},
) {
export function statsData(customDbPath: string, opts: { noTests?: boolean; config?: any } = {}) {
const db = openReadonlyOrFail(customDbPath);
try {
const noTests = opts.noTests || false;
Expand Down
1 change: 0 additions & 1 deletion src/domain/graph/builder/stages/build-edges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { loadNative } from '../../../../infrastructure/native.js';
import type {
Call,
ClassRelation,
Definition,
ExtractorOutput,
Import,
NativeAddon,
Expand Down
14 changes: 7 additions & 7 deletions src/domain/graph/builder/stages/detect-changes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type BetterSqlite3 from 'better-sqlite3';
import { closeDb } from '../../../../db/index.js';
import { debug, info } from '../../../../infrastructure/logger.js';
import { normalizePath } from '../../../../shared/constants.js';
import type { EngineOpts, ExtractorOutput } from '../../../../types.js';
import type { ExtractorOutput } from '../../../../types.js';
import { parseFilesAuto } from '../../../parser.js';
import { readJournal, writeJournalHeader } from '../../journal.js';
import type { PipelineContext } from '../context.js';
Expand Down Expand Up @@ -227,7 +227,7 @@ function mtimeAndHashTiers(
async function runPendingAnalysis(ctx: PipelineContext): Promise<boolean> {
const { db, opts, engineOpts, allFiles, rootDir } = ctx;
const needsCfg =
(opts as Record<string, unknown>)['cfg'] !== false &&
(opts as Record<string, unknown>).cfg !== false &&
(() => {
try {
return (
Expand All @@ -239,7 +239,7 @@ async function runPendingAnalysis(ctx: PipelineContext): Promise<boolean> {
}
})();
const needsDataflow =
(opts as Record<string, unknown>)['dataflow'] !== false &&
(opts as Record<string, unknown>).dataflow !== false &&
(() => {
try {
return (
Expand All @@ -255,7 +255,7 @@ async function runPendingAnalysis(ctx: PipelineContext): Promise<boolean> {
info('No file changes. Running pending analysis pass...');
const analysisOpts = {
...engineOpts,
dataflow: needsDataflow && (opts as Record<string, unknown>)['dataflow'] !== false,
dataflow: needsDataflow && (opts as Record<string, unknown>).dataflow !== false,
};
const analysisSymbols: Map<string, ExtractorOutput> = await parseFilesAuto(
allFiles,
Expand Down Expand Up @@ -359,7 +359,7 @@ function handleScopedBuild(ctx: PipelineContext): void {
(item) => item.relPath || normalizePath(path.relative(rootDir, item.file)),
);
let reverseDeps = new Set<string>();
if (!(opts as Record<string, unknown>)['noReverseDeps']) {
if (!(opts as Record<string, unknown>).noReverseDeps) {
const changedRelPaths = new Set<string>([...changePaths, ...ctx.removed]);
reverseDeps = findReverseDependencies(db, changedRelPaths, rootDir);
}
Expand All @@ -386,7 +386,7 @@ function handleIncrementalBuild(ctx: PipelineContext): void {
const { db, rootDir, opts } = ctx;
ctx.hasEmbeddings = detectHasEmbeddings(db);
let reverseDeps = new Set<string>();
if (!(opts as Record<string, unknown>)['noReverseDeps']) {
if (!(opts as Record<string, unknown>).noReverseDeps) {
const changedRelPaths = new Set<string>();
for (const item of ctx.parseChanges) {
changedRelPaths.add(item.relPath || normalizePath(path.relative(rootDir, item.file)));
Expand All @@ -410,7 +410,7 @@ function handleIncrementalBuild(ctx: PipelineContext): void {

export async function detectChanges(ctx: PipelineContext): Promise<void> {
const { db, allFiles, rootDir, incremental, forceFullRebuild, opts } = ctx;
if ((opts as Record<string, unknown>)['scope']) {
if ((opts as Record<string, unknown>).scope) {
handleScopedBuild(ctx);
return;
}
Expand Down
4 changes: 2 additions & 2 deletions src/domain/graph/cycles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ export function findCycles(
const idToLabel = new Map<string, string>();
for (const [id, attrs] of graph.nodes()) {
if (fileLevel) {
idToLabel.set(id, attrs['file'] as string);
idToLabel.set(id, attrs.file as string);
} else {
idToLabel.set(id, `${attrs['label']}|${attrs['file']}`);
idToLabel.set(id, `${attrs.label}|${attrs.file}`);
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/domain/graph/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type { BareSpecifier, BatchResolvedMap, ImportBatchItem, PathAliases } fr
// ── package.json exports resolution ─────────────────────────────────

/** Cache: packageDir → parsed exports field (or null) */
// biome-ignore lint/suspicious/noExplicitAny: package.json exports field has no fixed schema
const _exportsCache: Map<string, any> = new Map();

/**
Expand Down Expand Up @@ -56,7 +55,6 @@ function findPackageDir(packageName: string, rootDir: string): string | null {
* Read and cache the exports field from a package's package.json.
* Returns the exports value or null.
*/
// biome-ignore lint/suspicious/noExplicitAny: package.json exports field has no fixed schema
function getPackageExports(packageDir: string): any {
if (_exportsCache.has(packageDir)) return _exportsCache.get(packageDir);
try {
Expand Down
Loading
Loading