Skip to content

🐛 noImportCycles ignores subpath imports #7242

@npearson72

Description

@npearson72

Environment information

CLI:
  Version:                      2.1.4
  Color support:                true

Platform:
  CPU Architecture:             x86_64
  OS:                           macos

Environment:
  BIOME_LOG_PATH:               unset
  BIOME_LOG_PREFIX_NAME:        unset
  BIOME_CONFIG_PATH:            unset
  BIOME_THREADS:                unset
  NO_COLOR:                     unset
  TERM:                         tmux-256color
  JS_RUNTIME_VERSION:           v23.9.0
  JS_RUNTIME_NAME:              node
  NODE_PACKAGE_MANAGER:         pnpm/10.8.1

Biome Configuration:
  Status:                       Loaded successfully
  Path:                         biome.jsonc
  Formatter enabled:            false
  Linter enabled:               true
  Assist enabled:               true
  VCS enabled:                  false

Workspace:
  Open Documents:               0

What happened?

When using a monorepo (ex: Turborepo), aliasing paths does not always work. Instead, the same can be acheived using subpath imports:

https://nodejs.org/api/packages.html#subpath-imports

Essentially instead of a predefined alias like @ or ~, subpath imports uses a # symbol.

When used with biomejs, the noImportCycles does not pick up on the circular dependency.

This can be tested simply by creating a circular dependency import: a -> b -> a

When importing using the relative path that subpath imports allows, example:

Assuming both are exported in the same barrel file

// In 'A'
import { B } from '#lib'

// in 'B'
import { A } from '#lib`

^ Biome does not pick up on this being a problem

Where as if you change it to:

// In 'A'
import { B } from './lib'

// in 'B'
import { A } from './lib`

^ This is picked up by Biome


How to test

This can be tested/reproduced in the following repository:

https://github.com/npearson72/example-biome-bug

Steps to reproduce:

  1. git clone [email protected]:npearson72/example-biome-bug.git
  2. pnpm i

Then run either of the following commands:

pnpm lint

-- OR --

pnpm --filter @example/example-package lint

-- OR --

cd packages/example-package && pnpm exec biome lint

In this repo, I have several examples in packages/example-package/src/lib

You'll notice the following files:

  • A.tsx
  • B.tsx
  • C.tsx
  • D.tsx

A <-> B point to each using ./lib/B and ./lib/Arespectfully.

C <-> D point to each using #lib/D and #lib/C respectfully.

Either of these import styles (i.e. ./lib or #lib should reference the identical path.

However, when you run biome lint, only A and B errors are picked up:

src/lib/A.tsx:1:19 lint/nursery/noImportCycles ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ This import is part of a cycle.

  > 1 │ import { B } from './A';
      │                   ^^^^^
    2 │
    3 │ export const A = () => {

  ℹ This import resolves to src/lib/A.tsx
        ... which imports src/lib/A.tsx
        ... which is the file we're importing from.


src/lib/B.tsx:1:19 lint/nursery/noImportCycles ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ This import is part of a cycle.

  > 1 │ import { A } from './B';
      │                   ^^^^^
    2 │
    3 │ export const B = () => {

  ℹ This import resolves to src/lib/B.tsx
        ... which imports src/lib/B.tsx
        ... which is the file we're importing from.


Checked 7 files in 99ms. No fixes applied.
Found 2 errors.

NOTE: This bug was originally reported here #7191, but was closed before I was able to get an example repo prepared.

Expected result

I would expect it to understand subpath imports and treat them like any other path to detect circular dependencies.

Code of Conduct

  • I agree to follow Biome's Code of Conduct

Metadata

Metadata

Assignees

Labels

S-Bug-confirmedStatus: report has been confirmed as a valid bug

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions