Skip to content

Exported consts with non-recognized initializer shapes are not extracted as definitions at all #1819

Description

@carlos-alm

Summary

While investigating issue #1728 (exported-symbol detection), found a related but distinct and separate gap: some top-level const declarations are never extracted as a Definition at all (not just missing from exports — completely absent from symbols/definitions), because their initializer's node type isn't one of the recognized shapes (isConstantValue/is_js_literal: number/string/template_string/bool/null/undefined/array/object/regex/unary/binary/new_expression, or a function-like value).

Repro

// src/shared/version.ts
export const CODEGRAPH_VERSION: string = (
  JSON.parse(fs.readFileSync(path.join(__sharedDir, '..', '..', 'package.json'), 'utf-8')) as {
    version: string;
  }
).version;

CODEGRAPH_VERSION's initializer is a parenthesized expression whose value is a member-expression ((...).version) — not in the recognized "literal" shape list. Running codegraph where --file src/shared/version.ts -T --json shows only the file node; CODEGRAPH_VERSION does not appear in symbols at all (confirmed via direct DB query: src/shared/version.ts has zero non-file rows in nodes).

This is different from #1728: there, the symbol WAS in symbols/definitions but missing from exported. Here, the symbol never gets extracted as a definition in the first place, so it can't show up anywhere (dead-code audits, codegraph query, etc. are all blind to it).

A related, narrower gap: export let X = <bare literal> / export var X = <bare literal> (not the object-literal case, which is handled separately) also produce no top-level Definition, because handleVariableDeclarator's literal-constant branch requires isConst — this appears intentional-but-undocumented scope-limiting rather than a bug, but is worth confirming. Not currently used anywhere in this codebase's own source (verified via grep), so lower priority.

Suggested fix

Broaden the top-level-constant recognition (isConstantValue/is_js_literal and their call sites in extractConstDeclarators/handleConstIdentifierAssignment (TS) and handle_var_decl (Rust)) to also capture call_expression, member_expression, and parenthesized_expression-valued top-level const declarations as Definitions (kind constant), so any top-level constant is discoverable regardless of initializer complexity — mirroring how function declarations are captured regardless of body complexity.

Found while

Investigating and fixing #1728 (exported-symbol detection in where --file/codegraph exports). Not fixed there to keep that PR scoped to the export-list bug rather than the broader definition-extraction gap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions