ludo-technologies / ludo-technologies/polyscan

[BUG][auto] ts/import-counted-twice-as-module-and-constructor-name: new X() on an imported class double-counts the import in CBO

Open Beginner friendly
#151 1 comment 0 reactions 0 assignees View on GitHub
auto-filed bug good first issue P1
Dominant language
Go
Stars
12
Forks
7
Avg merge
5h 46m
Merged PRs (30d)
49

Description

## Summary

For JS/TS, a single import is counted **twice** in `cbo.classes[].metrics.dependent_classes` when the imported binding is used as a constructor: once under the normalized module name and once under the raw constructor identifier.

## Repro

`src/dep.ts`:
```ts
export class Widget {
render(): string { return 'w' }
}
```

`src/main.ts`:
```ts
import { Widget } from './dep'

export function run(): string {
return new Widget().render()
}
```

```
polyscan analyze --select cbo --format json .
```

## Expected

One import, one dependency: `deps=dep`, `coupling_count: 1`.

## Actual

```
file=main.ts coupling_count=2 deps=Widget,dep
```

Both `dep` and `Widget` appear for the same `import { Widget } from './dep'` statement.

## Real-world impact

In `rayriffy/elysia-rate-limit@ecb2515`:

- `src/services/defaultContext.ts` — `import AllocQuickLRU from '@alloc/quick-lru'` (L1), instantiated at L33, yields both `"@alloc/quick-lru"` and `"AllocQuickLRU"`:

```json
{"name":"defaultContext","metrics":{"coupling_count":6,"dependent_classes":["@alloc/quick-lru","@types/Context","@types/Options","AllocQuickLRU","item","logger"]}}
```

- `src/services/plugin.ts` — `import Elysia from 'elysia'` yields both `"elysia"` and `"Elysia"`; `import { DefaultContext } from './defaultContext'` yields both `"defaultContext"` and `"DefaultContext"`.

## Suspected cause

`extractInstantiationDependencies` in `polyscan/internal/js/analyzer/cbo.go` (~L149-160) records the raw constructor identifier without resolving it through the `importedIdentifiers` local-name to module map that `extractAttributeAccessDependencies` already builds and uses (~L232-244). Routing the constructor name through that same map should be enough.

## Priority

P1 — a wrong metric on a very common construct (`new X()` on an imported class). Local to one function, so likely a good first issue.

Found via the FP-audit skill in repo `rayriffy/elysia-rate-limit@ecb2515`.
polyscan version: `polyscan version 0.4.0`

Contributor guide

Open the contributing guide

Research direction

Read extractInstantiationDependencies in polyscan/internal/js/analyzer/cbo.go and compare its handling with extractAttributeAccessDependencies, especially the importedIdentifiers map. Run the provided TypeScript repro with polyscan analyze --select cbo --format json .; done means the imported class appears once as dep and coupling_count is 1 rather than listing both dep and Widget.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, typescript
Domain
devtools
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
85/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.