microsoft / microsoft/TypeScript
Autocomplete incorrectly suggests transitive files from monorepo package
Chưa có ai nhận issue này.
- 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
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- 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.
- Fork repository và làm thay đổi trên một nhánh.
- 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