microsoft / microsoft/TypeScript

Autocomplete incorrectly suggests transitive files from monorepo package

Đang mở
#63,033 7 bình luận 1 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Bug Corsa Domain: LS: Auto-import
Ngôn ngữ chính
Go
Star
111k
Fork
14.3k
Merge trung bình
2 ngày 4 giờ
Pull request đã merge (30 ngày)
132

Mô tả

### 🔎 Search Terms

"autocomplete transitive", "autocomplete export null", "auto-import workspace package", "monorepo auto-import"

### 🕗 Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about "Auto-import Heuristics and Preferences". Notably, I think this line from the FAQ is appropriate:

> It operates under a few key assumptions:
> ...
> 2. It's a bad idea to import things that won't work

### ⏯ Playground Link

This involves several files, so I've included a fourslash test below.

### 💻 Code

Below is a failing fourslash test that I put at `tests/cases/fourslash/server/autoImportProviderTransitiveLeak.ts`:

```ts
///

// @Filename: /home/src/workspaces/project/tsconfig.base.json
//// {
//// "compilerOptions": {
//// "module": "nodenext",
//// "composite": true,
//// "outDir": "${configDir}/dist"
//// }
//// }

// packages/foo

// @Filename: /home/src/workspaces/project/packages/foo/package.json
//// { "name": "@packages/foo", "type": "module", "version": "1.0.0", "exports": { ".": { "types": "./src/index.ts", "default": "./dist/index.js" }, "./internal/*": null } }

// @Filename: /home/src/workspaces/project/packages/foo/tsconfig.json
//// { "extends": "../../tsconfig.base.json" }

// @Filename: /home/src/workspaces/project/packages/foo/src/internal/index.ts
//// export function fooInternal() { console.log("foo"); }

// @Filename: /home/src/workspaces/project/packages/foo/src/index.ts
//// import { fooInternal } from "./internal/index.js"
////
//// export function foo() { fooInternal(); }

// packages/bar

// @Filename: /home/src/workspaces/project/packages/bar/package.json
//// { "name": "@packages/bar", "type": "module", "version": "1.0.0", "exports": { ".": { "types": "./src/index.ts", "default": "./dist/index.js" }, "./internal/*": null }, "dependencies": { "@packages/foo": "*" } }

// @Filename: /home/src/workspaces/project/packages/bar/tsconfig.json
//// { "extends": "../../tsconfig.base.json" }

// @Filename: /home/src/workspaces/project/packages/bar/src/index.ts
//// fo/**/

// npm workspaces

// @Filename: /home/src/workspaces/project/package.json
//// { "workspaces": ["packages/*"], "type": "module" }

// @link: /home/src/workspaces/project/packages/foo -> /home/src/workspaces/project/node_modules/@packages/foo
// @link: /home/src/workspaces/project/packages/bar -> /home/src/workspaces/project/node_modules/@packages/bar

goTo.marker("");

verify.completions({
marker: "",
includes: [
{
name: "foo",
source: "@packages/foo",
sourceDisplay: "@packages/foo",
hasAction: true,
sortText: completion.SortText.AutoImportSuggestions,
},
],
excludes: ["fooInternal"],
preferences: {
includeCompletionsForModuleExports: true,
allowIncompleteCompletions: true,
},
});

```

### 🙁 Actual behavior

When replicating this in a repository, autocomplete suggests `fooInternal` via a relative path import. Accepting this import results in the following code that has a red squiggly on the import line and fails to compile:

```
import { fooInternal } from "../../foo/src/internal/index.js";

fooInternal
```

The error is:
```
File '/packages/foo/src/internal/index.ts' is not under 'rootDir' '/packages/bar/src'. 'rootDir' is expected to contain all source files.
```

### 🙂 Expected behavior

I believe that `fooInternal` should not be suggested because it's "a bad idea to import things that won't work" per the FAQ. This import won't work for two reasons:

1. It is not in the current Typescript project, nor is it referenced.
2. Even if it suggested the package path and not a relative path, it is blocked by the NodeJS exports.

### Additional information about the issue

After doing some initial investigation with Claude to identify the source of the bug, I noticed that `getNodeModulesPackageNameFromFileName` might have theoretically worked here, but it does not because these are symlinks due to being workspace packages, which are resolved to a non-`node_modules` directory. I tried the test with `"preserveSymlinks": true`, however, and the bug still occurred. This appears to be because `AutoImportProviderProject` unconditionally resolves the symlink, which may or may not be appropriate, I'm not sure.

I'm happy to provide more context about _why_ we want `fooInternal` to not be suggested, but I hope it's clear from the reproduction case.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu với tests/cases/fourslash/server/autoImportProviderTransitiveLeak.ts và chạy test fourslash đang bị lỗi. Theo dõi getNodeModulesPackageNameFromFileName và AutoImportProviderProject trong khi điều tra cách các symlink của workspace và package exports được xử lý. Được xem là hoàn tất khi foo vẫn được đề xuất từ @packages/foo, còn fooInternal bị loại trừ.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
node.js, typescript
Lĩnh vực
developer-experience, tooling
Loại issue
Lỗi
Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
50/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.