Allow existing imports in file to supersede package.json filter (#59604)

This commit is contained in:
Andrew Branch
2024-08-15 15:00:31 -07:00
committed by GitHub
parent 5fd6a6fd8d
commit bcb1545aa3
12 changed files with 7233 additions and 25 deletions
+3 -2
View File
@@ -5461,7 +5461,7 @@ export const enum NodeBuilderFlags {
AllowEmptyIndexInfoType = 1 << 21,
// Errors (cont.)
AllowNodeModulesRelativePaths = 1 << 26,
IgnoreErrors = AllowThisInObjectLiteral | AllowQualifiedNameInPlaceOfIdentifier | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple | AllowEmptyIndexInfoType | AllowNodeModulesRelativePaths,
@@ -9855,6 +9855,7 @@ export interface ModulePath {
export interface ResolvedModuleSpecifierInfo {
kind: "node_modules" | "paths" | "redirect" | "relative" | "ambient" | undefined;
modulePaths: readonly ModulePath[] | undefined;
packageName: string | undefined;
moduleSpecifiers: readonly string[] | undefined;
isBlockedByPackageJsonDependencies: boolean | undefined;
}
@@ -9868,7 +9869,7 @@ export interface ModuleSpecifierOptions {
export interface ModuleSpecifierCache {
get(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions): Readonly<ResolvedModuleSpecifierInfo> | undefined;
set(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, kind: ResolvedModuleSpecifierInfo["kind"], modulePaths: readonly ModulePath[], moduleSpecifiers: readonly string[]): void;
setBlockedByPackageJsonDependencies(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, isBlockedByPackageJsonDependencies: boolean): void;
setBlockedByPackageJsonDependencies(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, packageName: string | undefined, isBlockedByPackageJsonDependencies: boolean): void;
setModulePaths(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, modulePaths: readonly ModulePath[]): void;
clear(): void;
count(): number;
+7 -5
View File
@@ -28,7 +28,7 @@ export function createModuleSpecifierCache(host: ModuleSpecifierResolutionCacheH
return cache.get(toFileName);
},
set(fromFileName, toFileName, preferences, options, kind, modulePaths, moduleSpecifiers) {
ensureCache(fromFileName, preferences, options).set(toFileName, createInfo(kind, modulePaths, moduleSpecifiers, /*isBlockedByPackageJsonDependencies*/ false));
ensureCache(fromFileName, preferences, options).set(toFileName, createInfo(kind, modulePaths, moduleSpecifiers, /*packageName*/ undefined, /*isBlockedByPackageJsonDependencies*/ false));
// If any module specifiers were generated based off paths in node_modules,
// a package.json file in that package was read and is an input to the cached.
@@ -58,17 +58,18 @@ export function createModuleSpecifierCache(host: ModuleSpecifierResolutionCacheH
info.modulePaths = modulePaths;
}
else {
cache.set(toFileName, createInfo(/*kind*/ undefined, modulePaths, /*moduleSpecifiers*/ undefined, /*isBlockedByPackageJsonDependencies*/ undefined));
cache.set(toFileName, createInfo(/*kind*/ undefined, modulePaths, /*moduleSpecifiers*/ undefined, /*packageName*/ undefined, /*isBlockedByPackageJsonDependencies*/ undefined));
}
},
setBlockedByPackageJsonDependencies(fromFileName, toFileName, preferences, options, isBlockedByPackageJsonDependencies) {
setBlockedByPackageJsonDependencies(fromFileName, toFileName, preferences, options, packageName, isBlockedByPackageJsonDependencies) {
const cache = ensureCache(fromFileName, preferences, options);
const info = cache.get(toFileName);
if (info) {
info.isBlockedByPackageJsonDependencies = isBlockedByPackageJsonDependencies;
info.packageName = packageName;
}
else {
cache.set(toFileName, createInfo(/*kind*/ undefined, /*modulePaths*/ undefined, /*moduleSpecifiers*/ undefined, isBlockedByPackageJsonDependencies));
cache.set(toFileName, createInfo(/*kind*/ undefined, /*modulePaths*/ undefined, /*moduleSpecifiers*/ undefined, packageName, isBlockedByPackageJsonDependencies));
}
},
clear() {
@@ -103,8 +104,9 @@ export function createModuleSpecifierCache(host: ModuleSpecifierResolutionCacheH
kind: ResolvedModuleSpecifierInfo["kind"] | undefined,
modulePaths: readonly ModulePath[] | undefined,
moduleSpecifiers: readonly string[] | undefined,
packageName: string | undefined,
isBlockedByPackageJsonDependencies: boolean | undefined,
): ResolvedModuleSpecifierInfo {
return { kind, modulePaths, moduleSpecifiers, isBlockedByPackageJsonDependencies };
return { kind, modulePaths, moduleSpecifiers, packageName, isBlockedByPackageJsonDependencies };
}
}
+2 -1
View File
@@ -35,6 +35,7 @@ import {
ExportKind,
ExportMapInfoKey,
factory,
fileContainsPackageImport,
findAncestor,
first,
firstDefined,
@@ -1543,7 +1544,7 @@ function getExportInfos(
const moduleSpecifierResolutionHost = getModuleSpecifierResolutionHost(isFromPackageJson);
if (
toFile && isImportableFile(program, fromFile, toFile, preferences, packageJsonFilter, moduleSpecifierResolutionHost, moduleSpecifierCache) ||
!toFile && packageJsonFilter.allowsImportingAmbientModule(moduleSymbol, moduleSpecifierResolutionHost)
(!toFile && packageJsonFilter.allowsImportingAmbientModule(moduleSymbol, moduleSpecifierResolutionHost) || fileContainsPackageImport(fromFile, stripQuotes(moduleSymbol.name)))
) {
const checker = program.getTypeChecker();
originalSymbolToExportInfos.add(getUniqueSymbolId(exportedSymbol, checker).toString(), { symbol: exportedSymbol, moduleSymbol, moduleFileName: toFile?.fileName, exportKind, targetFlags: skipAlias(exportedSymbol, checker).flags, isFromPackageJson });
+3 -3
View File
@@ -63,6 +63,7 @@ import {
Expression,
ExpressionWithTypeArguments,
factory,
fileContainsPackageImport,
filter,
find,
findAncestor,
@@ -4207,9 +4208,8 @@ function getCompletionData(
if (JsTyping.nodeCoreModules.has(moduleName) && startsWith(moduleName, "node:") !== shouldUseUriStyleNodeCoreModules(sourceFile, program)) {
return false;
}
return packageJsonFilter
? packageJsonFilter.allowsImportingAmbientModule(info.moduleSymbol, getModuleSpecifierResolutionHost(info.isFromPackageJson))
: true;
return (packageJsonFilter?.allowsImportingAmbientModule(info.moduleSymbol, getModuleSpecifierResolutionHost(info.isFromPackageJson)) ?? true)
|| fileContainsPackageImport(sourceFile, moduleName);
}
return isImportableFile(
info.isFromPackageJson ? packageJsonAutoImportProvider! : program,
+9 -4
View File
@@ -374,7 +374,7 @@ export function isImportableFile(
if (from === to) return false;
const cachedResult = moduleSpecifierCache?.get(from.path, to.path, preferences, {});
if (cachedResult?.isBlockedByPackageJsonDependencies !== undefined) {
return !cachedResult.isBlockedByPackageJsonDependencies;
return !cachedResult.isBlockedByPackageJsonDependencies || !!cachedResult.packageName && fileContainsPackageImport(from, cachedResult.packageName);
}
const getCanonicalFileName = hostGetCanonicalFileName(moduleSpecifierResolutionHost);
@@ -394,14 +394,19 @@ export function isImportableFile(
);
if (packageJsonFilter) {
const isAutoImportable = hasImportablePath && packageJsonFilter.allowsImportingSourceFile(to, moduleSpecifierResolutionHost);
moduleSpecifierCache?.setBlockedByPackageJsonDependencies(from.path, to.path, preferences, {}, !isAutoImportable);
return isAutoImportable;
const importInfo = hasImportablePath ? packageJsonFilter.getSourceFileInfo(to, moduleSpecifierResolutionHost) : undefined;
moduleSpecifierCache?.setBlockedByPackageJsonDependencies(from.path, to.path, preferences, {}, importInfo?.packageName, !importInfo?.importable);
return !!importInfo?.importable || !!importInfo?.packageName && fileContainsPackageImport(from, importInfo.packageName);
}
return hasImportablePath;
}
/** @internal */
export function fileContainsPackageImport(sourceFile: SourceFile, packageName: string) {
return sourceFile.imports && sourceFile.imports.some(i => i.text === packageName || i.text.startsWith(packageName + "/"));
}
/**
* Don't include something from a `node_modules` that isn't actually reachable by a global import.
* A relative import to node_modules is usually a bad idea.
+12 -10
View File
@@ -3740,7 +3740,7 @@ export function createPackageJsonInfo(fileName: string, host: { readFile?(fileNa
/** @internal */
export interface PackageJsonImportFilter {
allowsImportingAmbientModule: (moduleSymbol: Symbol, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost) => boolean;
allowsImportingSourceFile: (sourceFile: SourceFile, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost) => boolean;
getSourceFileInfo: (sourceFile: SourceFile, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost) => { importable: boolean; packageName?: string; };
/**
* Use for a specific module specifier that has already been resolved.
* Use `allowsImportingAmbientModule` or `allowsImportingSourceFile` to resolve
@@ -3757,10 +3757,10 @@ export function createPackageJsonImportFilter(fromFile: SourceFile | FutureSourc
let usesNodeCoreModules: boolean | undefined;
let ambientModuleCache: Map<Symbol, boolean> | undefined;
let sourceFileCache: Map<SourceFile, boolean> | undefined;
let sourceFileCache: Map<SourceFile, { importable: boolean; packageName?: string; }> | undefined;
return {
allowsImportingAmbientModule,
allowsImportingSourceFile,
getSourceFileInfo,
allowsImportingSpecifier,
};
@@ -3808,9 +3808,9 @@ export function createPackageJsonImportFilter(fromFile: SourceFile | FutureSourc
return result;
}
function allowsImportingSourceFile(sourceFile: SourceFile, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost): boolean {
function getSourceFileInfo(sourceFile: SourceFile, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost): { importable: boolean; packageName?: string; } {
if (!packageJsons.length) {
return true;
return { importable: true, packageName: undefined };
}
if (!sourceFileCache) {
@@ -3823,13 +3823,15 @@ export function createPackageJsonImportFilter(fromFile: SourceFile | FutureSourc
}
}
const moduleSpecifier = getNodeModulesPackageNameFromFileName(sourceFile.fileName, moduleSpecifierResolutionHost);
if (!moduleSpecifier) {
sourceFileCache.set(sourceFile, true);
return true;
const packageName = getNodeModulesPackageNameFromFileName(sourceFile.fileName, moduleSpecifierResolutionHost);
if (!packageName) {
const result = { importable: true, packageName };
sourceFileCache.set(sourceFile, result);
return result;
}
const result = moduleSpecifierIsCoveredByPackageJson(moduleSpecifier);
const importable = moduleSpecifierIsCoveredByPackageJson(packageName);
const result = { importable, packageName };
sourceFileCache.set(sourceFile, result);
return result;
}
@@ -0,0 +1,733 @@
currentDirectory:: / useCaseSensitiveFileNames: false
Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist
//// [/index.ts]
import { useState } from "react";
useMemo
//// [/lib.d.ts]
lib.d.ts-Text
//// [/lib.decorators.d.ts]
lib.decorators.d.ts-Text
//// [/lib.decorators.legacy.d.ts]
lib.decorators.legacy.d.ts-Text
//// [/node_modules/@types/react/index.d.ts]
export declare function useMemo(): void;
export declare function useState(): void;
//// [/package.json]
{}
Info seq [hh:mm:ss:mss] request:
{
"seq": 0,
"type": "request",
"arguments": {
"file": "/node_modules/@types/react/index.d.ts"
},
"command": "open"
}
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /node_modules/@types/react/index.d.ts ProjectRootPath: undefined:: Result: undefined
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /lib.d.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /lib.decorators.d.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /lib.decorators.legacy.d.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /node_modules/@types/react/package.json 2000 undefined Project: /dev/null/inferredProject1* WatchType: File location affecting resolution
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /node_modules/@types/react/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /node_modules/@types/react/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
Info seq [hh:mm:ss:mss] Files (4)
/lib.d.ts Text-1 lib.d.ts-Text
/lib.decorators.d.ts Text-1 lib.decorators.d.ts-Text
/lib.decorators.legacy.d.ts Text-1 lib.decorators.legacy.d.ts-Text
/node_modules/@types/react/index.d.ts SVC-1-0 "export declare function useMemo(): void;\nexport declare function useState(): void;"
../../../lib.d.ts
Default library for target 'es5'
../../../lib.decorators.d.ts
Library referenced via 'decorators' from file '../../../lib.d.ts'
../../../lib.decorators.legacy.d.ts
Library referenced via 'decorators.legacy' from file '../../../lib.d.ts'
index.d.ts
Root file specified for compilation
Entry point for implicit type library 'react'
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /node_modules/@types/react/index.d.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject1*
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "open",
"request_seq": 0,
"success": true,
"performanceData": {
"updateGraphDurationMs": *
}
}
After Request
watchedFiles::
/lib.d.ts: *new*
{"pollingInterval":500}
/lib.decorators.d.ts: *new*
{"pollingInterval":500}
/lib.decorators.legacy.d.ts: *new*
{"pollingInterval":500}
/node_modules/@types/react/package.json: *new*
{"pollingInterval":2000}
watchedDirectoriesRecursive::
/node_modules/@types/react/node_modules/@types: *new*
{}
Projects::
/dev/null/inferredProject1* (Inferred) *new*
projectStateVersion: 1
projectProgramVersion: 1
ScriptInfos::
/lib.d.ts *new*
version: Text-1
containingProjects: 1
/dev/null/inferredProject1*
/lib.decorators.d.ts *new*
version: Text-1
containingProjects: 1
/dev/null/inferredProject1*
/lib.decorators.legacy.d.ts *new*
version: Text-1
containingProjects: 1
/dev/null/inferredProject1*
/node_modules/@types/react/index.d.ts (Open) *new*
version: SVC-1-0
containingProjects: 1
/dev/null/inferredProject1* *default*
Info seq [hh:mm:ss:mss] request:
{
"seq": 1,
"type": "request",
"arguments": {
"file": "/index.ts"
},
"command": "open"
}
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /index.ts ProjectRootPath: undefined:: Result: undefined
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject2*
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /node_modules/@types/react/package.json 2000 undefined Project: /dev/null/inferredProject2* WatchType: File location affecting resolution
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject2* projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject2*' (Inferred)
Info seq [hh:mm:ss:mss] Files (5)
/lib.d.ts Text-1 lib.d.ts-Text
/lib.decorators.d.ts Text-1 lib.decorators.d.ts-Text
/lib.decorators.legacy.d.ts Text-1 lib.decorators.legacy.d.ts-Text
/node_modules/@types/react/index.d.ts SVC-1-0 "export declare function useMemo(): void;\nexport declare function useState(): void;"
/index.ts SVC-1-0 "import { useState } from \"react\";\nuseMemo"
lib.d.ts
Default library for target 'es5'
lib.decorators.d.ts
Library referenced via 'decorators' from file 'lib.d.ts'
lib.decorators.legacy.d.ts
Library referenced via 'decorators.legacy' from file 'lib.d.ts'
node_modules/@types/react/index.d.ts
Imported via "react" from file 'index.ts'
Entry point for implicit type library 'react'
index.ts
Root file specified for compilation
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /package.json 250 undefined WatchType: package.json file
Info seq [hh:mm:ss:mss] `remove Project::
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
Info seq [hh:mm:ss:mss] Files (4)
/lib.d.ts
/lib.decorators.d.ts
/lib.decorators.legacy.d.ts
/node_modules/@types/react/index.d.ts
../../../lib.d.ts
Default library for target 'es5'
../../../lib.decorators.d.ts
Library referenced via 'decorators' from file '../../../lib.d.ts'
../../../lib.decorators.legacy.d.ts
Library referenced via 'decorators.legacy' from file '../../../lib.d.ts'
index.d.ts
Root file specified for compilation
Entry point for implicit type library 'react'
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /node_modules/@types/react/package.json 2000 undefined Project: /dev/null/inferredProject1* WatchType: File location affecting resolution
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Close:: WatchInfo: /node_modules/@types/react/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /node_modules/@types/react/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject2*' (Inferred)
Info seq [hh:mm:ss:mss] Files (5)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /node_modules/@types/react/index.d.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject2*
Info seq [hh:mm:ss:mss] FileName: /index.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject2*
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "open",
"request_seq": 1,
"success": true,
"performanceData": {
"updateGraphDurationMs": *
}
}
After Request
watchedFiles::
/lib.d.ts:
{"pollingInterval":500}
/lib.decorators.d.ts:
{"pollingInterval":500}
/lib.decorators.legacy.d.ts:
{"pollingInterval":500}
/node_modules/@types/react/package.json:
{"pollingInterval":2000} *new*
/package.json: *new*
{"pollingInterval":250}
watchedFiles *deleted*::
/node_modules/@types/react/package.json:
{"pollingInterval":2000}
watchedDirectoriesRecursive *deleted*::
/node_modules/@types/react/node_modules/@types:
{}
Projects::
/dev/null/inferredProject1* (Inferred) *deleted*
projectStateVersion: 2 *changed*
projectProgramVersion: 1
dirty: true *changed*
isClosed: true *changed*
isOrphan: true *changed*
/dev/null/inferredProject2* (Inferred) *new*
projectStateVersion: 1
projectProgramVersion: 1
ScriptInfos::
/index.ts (Open) *new*
version: SVC-1-0
containingProjects: 1
/dev/null/inferredProject2* *default*
/lib.d.ts *changed*
version: Text-1
containingProjects: 1 *changed*
/dev/null/inferredProject2* *new*
/dev/null/inferredProject1* *deleted*
/lib.decorators.d.ts *changed*
version: Text-1
containingProjects: 1 *changed*
/dev/null/inferredProject2* *new*
/dev/null/inferredProject1* *deleted*
/lib.decorators.legacy.d.ts *changed*
version: Text-1
containingProjects: 1 *changed*
/dev/null/inferredProject2* *new*
/dev/null/inferredProject1* *deleted*
/node_modules/@types/react/index.d.ts (Open) *changed*
version: SVC-1-0
containingProjects: 1 *changed*
/dev/null/inferredProject2* *default* *new*
/dev/null/inferredProject1* *deleted*
Info seq [hh:mm:ss:mss] request:
{
"seq": 2,
"type": "request",
"arguments": {
"preferences": {}
},
"command": "configure"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "configure",
"request_seq": 2,
"success": true
}
Info seq [hh:mm:ss:mss] request:
{
"seq": 3,
"type": "request",
"arguments": {
"file": "/index.ts",
"includeLinePosition": true
},
"command": "syntacticDiagnosticsSync"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "syntacticDiagnosticsSync",
"request_seq": 3,
"success": true,
"body": []
}
Info seq [hh:mm:ss:mss] request:
{
"seq": 4,
"type": "request",
"arguments": {
"file": "/index.ts",
"includeLinePosition": true
},
"command": "semanticDiagnosticsSync"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "semanticDiagnosticsSync",
"request_seq": 4,
"success": true,
"body": [
{
"message": "Cannot find name 'useMemo'.",
"start": 34,
"length": 7,
"category": "error",
"code": 2304,
"startLocation": {
"line": 2,
"offset": 1
},
"endLocation": {
"line": 2,
"offset": 8
}
}
]
}
Info seq [hh:mm:ss:mss] request:
{
"seq": 5,
"type": "request",
"arguments": {
"file": "/index.ts",
"includeLinePosition": true
},
"command": "suggestionDiagnosticsSync"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "suggestionDiagnosticsSync",
"request_seq": 5,
"success": true,
"body": [
{
"message": "'useState' is declared but its value is never read.",
"start": 0,
"length": 33,
"category": "suggestion",
"code": 6133,
"startLocation": {
"line": 1,
"offset": 1
},
"endLocation": {
"line": 1,
"offset": 34
},
"reportsUnnecessary": true
}
]
}
Info seq [hh:mm:ss:mss] request:
{
"seq": 6,
"type": "request",
"arguments": {
"file": "/index.ts",
"startLine": 2,
"startOffset": 1,
"endLine": 2,
"endOffset": 8,
"errorCodes": [
2304
]
},
"command": "getCodeFixes"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "getCodeFixes",
"request_seq": 6,
"success": true,
"body": [
{
"fixName": "import",
"description": "Update import from \"react\"",
"changes": [
{
"fileName": "/index.ts",
"textChanges": [
{
"start": {
"line": 1,
"offset": 10
},
"end": {
"line": 1,
"offset": 10
},
"newText": "useMemo, "
}
]
}
]
}
]
}
Info seq [hh:mm:ss:mss] request:
{
"seq": 7,
"type": "request",
"arguments": {
"file": "/index.ts",
"startLine": 1,
"startOffset": 1,
"endLine": 1,
"endOffset": 34,
"errorCodes": [
6133
]
},
"command": "getCodeFixes"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "getCodeFixes",
"request_seq": 7,
"success": true,
"body": [
{
"fixName": "unusedIdentifier",
"description": "Remove import from 'react'",
"changes": [
{
"fileName": "/index.ts",
"textChanges": [
{
"start": {
"line": 1,
"offset": 1
},
"end": {
"line": 2,
"offset": 1
},
"newText": ""
}
]
}
]
}
]
}
Info seq [hh:mm:ss:mss] request:
{
"seq": 8,
"type": "request",
"arguments": {
"file": "/index.ts",
"line": 1,
"offset": 10,
"endLine": 1,
"endOffset": 10,
"insertString": "useMemo, "
},
"command": "change"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "change",
"request_seq": 8,
"success": true
}
After Request
Projects::
/dev/null/inferredProject2* (Inferred) *changed*
projectStateVersion: 2 *changed*
projectProgramVersion: 1
dirty: true *changed*
ScriptInfos::
/index.ts (Open) *changed*
version: SVC-1-1 *changed*
containingProjects: 1
/dev/null/inferredProject2* *default*
/lib.d.ts
version: Text-1
containingProjects: 1
/dev/null/inferredProject2*
/lib.decorators.d.ts
version: Text-1
containingProjects: 1
/dev/null/inferredProject2*
/lib.decorators.legacy.d.ts
version: Text-1
containingProjects: 1
/dev/null/inferredProject2*
/node_modules/@types/react/index.d.ts (Open)
version: SVC-1-0
containingProjects: 1
/dev/null/inferredProject2* *default*
Info seq [hh:mm:ss:mss] request:
{
"seq": 9,
"type": "request",
"arguments": {
"file": "/index.ts",
"line": 1,
"offset": 10,
"endLine": 1,
"endOffset": 19,
"insertString": ""
},
"command": "change"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "change",
"request_seq": 9,
"success": true
}
After Request
ScriptInfos::
/index.ts (Open) *changed*
version: SVC-1-2 *changed*
containingProjects: 1
/dev/null/inferredProject2* *default*
/lib.d.ts
version: Text-1
containingProjects: 1
/dev/null/inferredProject2*
/lib.decorators.d.ts
version: Text-1
containingProjects: 1
/dev/null/inferredProject2*
/lib.decorators.legacy.d.ts
version: Text-1
containingProjects: 1
/dev/null/inferredProject2*
/node_modules/@types/react/index.d.ts (Open)
version: SVC-1-0
containingProjects: 1
/dev/null/inferredProject2* *default*
Info seq [hh:mm:ss:mss] request:
{
"seq": 10,
"type": "request",
"arguments": {
"file": "/index.ts",
"line": 1,
"offset": 1,
"endLine": 2,
"endOffset": 1,
"insertString": ""
},
"command": "change"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "change",
"request_seq": 10,
"success": true
}
After Request
ScriptInfos::
/index.ts (Open) *changed*
version: SVC-1-3 *changed*
containingProjects: 1
/dev/null/inferredProject2* *default*
/lib.d.ts
version: Text-1
containingProjects: 1
/dev/null/inferredProject2*
/lib.decorators.d.ts
version: Text-1
containingProjects: 1
/dev/null/inferredProject2*
/lib.decorators.legacy.d.ts
version: Text-1
containingProjects: 1
/dev/null/inferredProject2*
/node_modules/@types/react/index.d.ts (Open)
version: SVC-1-0
containingProjects: 1
/dev/null/inferredProject2* *default*
Info seq [hh:mm:ss:mss] request:
{
"seq": 11,
"type": "request",
"arguments": {
"preferences": {}
},
"command": "configure"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "configure",
"request_seq": 11,
"success": true
}
Info seq [hh:mm:ss:mss] request:
{
"seq": 12,
"type": "request",
"arguments": {
"file": "/index.ts",
"includeLinePosition": true
},
"command": "syntacticDiagnosticsSync"
}
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject2*
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject2* projectStateVersion: 2 projectProgramVersion: 1 structureChanged: true structureIsReused:: SafeModules Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject2*' (Inferred)
Info seq [hh:mm:ss:mss] Files (5)
/lib.d.ts Text-1 lib.d.ts-Text
/lib.decorators.d.ts Text-1 lib.decorators.d.ts-Text
/lib.decorators.legacy.d.ts Text-1 lib.decorators.legacy.d.ts-Text
/index.ts SVC-1-3 "useMemo"
/node_modules/@types/react/index.d.ts SVC-1-0 "export declare function useMemo(): void;\nexport declare function useState(): void;"
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "syntacticDiagnosticsSync",
"request_seq": 12,
"success": true,
"performanceData": {
"updateGraphDurationMs": *
},
"body": []
}
After Request
Projects::
/dev/null/inferredProject2* (Inferred) *changed*
projectStateVersion: 2
projectProgramVersion: 2 *changed*
dirty: false *changed*
Info seq [hh:mm:ss:mss] request:
{
"seq": 13,
"type": "request",
"arguments": {
"file": "/index.ts",
"includeLinePosition": true
},
"command": "semanticDiagnosticsSync"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "semanticDiagnosticsSync",
"request_seq": 13,
"success": true,
"body": [
{
"message": "Cannot find name 'useMemo'.",
"start": 0,
"length": 7,
"category": "error",
"code": 2304,
"startLocation": {
"line": 1,
"offset": 1
},
"endLocation": {
"line": 1,
"offset": 8
}
}
]
}
Info seq [hh:mm:ss:mss] request:
{
"seq": 14,
"type": "request",
"arguments": {
"file": "/index.ts",
"includeLinePosition": true
},
"command": "suggestionDiagnosticsSync"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "suggestionDiagnosticsSync",
"request_seq": 14,
"success": true,
"body": []
}
Info seq [hh:mm:ss:mss] request:
{
"seq": 15,
"type": "request",
"arguments": {
"file": "/index.ts",
"startLine": 1,
"startOffset": 1,
"endLine": 1,
"endOffset": 8,
"errorCodes": [
2304
]
},
"command": "getCodeFixes"
}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "getCodeFixes",
"request_seq": 15,
"success": true,
"body": []
}
@@ -0,0 +1,24 @@
/// <reference path="../fourslash.ts" />
// @module: preserve
// @Filename: /node_modules/@types/react/index.d.ts
//// export declare function useMemo(): void;
//// export declare function useState(): void;
// @Filename: /package.json
//// {}
// @Filename: /index.ts
//// import { useState } from "react";
//// useMemo/**/
goTo.marker("");
verify.importFixAtPosition([
`import { useMemo, useState } from "react";
useMemo`
]);
edit.deleteLine(0);
goTo.marker("");
verify.importFixAtPosition([]);
@@ -0,0 +1,25 @@
/// <reference path="../fourslash.ts" />
// @module: preserve
// @Filename: /node_modules/@types/react/index.d.ts
//// export declare function useMemo(): void;
//// export declare function useState(): void;
// @Filename: /package.json
//// {}
// @Filename: /index.ts
//// useMemo/**/
goTo.marker("");
verify.importFixAtPosition([]);
goTo.bof();
edit.insertLine(`import { useState } from "react";`);
goTo.marker("");
verify.importFixAtPosition([
`import { useMemo, useState } from "react";
useMemo`
]);
@@ -0,0 +1,27 @@
/// <reference path="../fourslash.ts" />
// @module: preserve
// @Filename: /node_modules/@types/node/index.d.ts
//// declare module "node:fs" {
//// export function readFile(): void;
//// export function writeFile(): void;
//// }
// @Filename: /package.json
//// {}
// @Filename: /index.ts
//// readFile/**/
goTo.marker("");
verify.importFixAtPosition([]);
goTo.bof();
edit.insertLine(`import { writeFile } from "node:fs";`);
goTo.marker("");
verify.importFixAtPosition([
`import { readFile, writeFile } from "node:fs";
readFile`
]);