Skip to content

resolution: an imports edge lands on a class property or interface method that merely shares the imported name (import path from 'node:path'SomeType::path) #1537

Description

@ctype-lab

An import of something the project does not contain — a Node built-in, an npm
package — is unresolvable, so the name-matcher falls back to finding any node with
that name. Import names are short and generic (path, url, join, events,
default), so a class property or interface method with the same name is almost
always present somewhere, and the import binds to it.

Nothing in any supported language lets an import bind to a member that only exists
inside a type. You import the type.

Environment

  • codegraph: 1.5.0 (npm), reproduced on main @ c6aaa20
  • Backend: node:sqlite (WAL)
  • Platform: Linux x64
  • src/resolution/ only — no kernel counterpart, both extraction paths identical

Repro

src/types.ts

export class Request {
  path = '';
  url = '';
}

src/run.ts

import * as path from 'node:path';

export function run() {
  return path.join('a', 'b');
}
codegraph init .
sqlite3 .codegraph/codegraph.db "
  SELECT s.file_path, t.kind, t.qualified_name
  FROM edges e JOIN nodes s ON s.id=e.source JOIN nodes t ON t.id=e.target
  WHERE e.kind='imports';"

Expected

No imports edge — node:path is not in the project.

Actual

src/run.ts | property | Request::path

Impact (measured on this repository, 571 files)

imports target kind edges correct?
method 19 no — all 19
property 4 no — all 4

Every one is a coincidence:

Walker::join          @codegraph-kernel/src/rustlang.rs   × 15
Telemetry::events     @src/telemetry/index.ts             × 2
FetchCall::url        @__tests__/telemetry.test.ts        × 2
PipelineRequest::path @__tests__/fixtures/…/pipeline/types.ts
Tables::default       @codegraph-kernel/src/buffers.rs
…

A second project — a 2,669-node Rust/TypeScript app — carries 28 more of the
same, every one an imports edge landing on a method.

These are phantom file-to-file dependencies. They feed codegraph_explore's file
ranking and impact radius as if the importing file genuinely depended on the file
that happens to declare a member of that name.

The count scales with how many member nodes the graph holds, so it is not fixed at
23. Prototyping TS interface-member extraction (interface methods and properties as
nodes) took imports → property on this repository from 4 to 377 in a single
re-index — the same bug, simply given more surface to hit.

Cause

Same root as #1536matchByExactName applies no kind constraint to its candidate
pool, and scoreCandidate treats kind as a bonus rather than a requirement. For
imports there is no bonus of any kind, so a member ranks exactly like a top-level
definition, and the single-candidate shortcut takes it outright at confidence 0.9.

Fixed by the same mechanism as #1536, which is why one PR closes both.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions