mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Handle already released source files that dont match scriptKind (#54401)
This commit is contained in:
parent
da686774dc
commit
c64a378ef9
@ -1713,9 +1713,13 @@ export function createLanguageService(
|
||||
// calculate this early so it's not undefined if downleveled to a var (or, if emitted
|
||||
// as a const variable without downleveling, doesn't crash).
|
||||
const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);
|
||||
let releasedScriptKinds: Set<Path> | undefined = new Set();
|
||||
|
||||
// If the program is already up-to-date, we can reuse it
|
||||
if (isProgramUptoDate(program, rootFileNames, newSettings, (_path, fileName) => host.getScriptVersion(fileName), fileName => compilerHost!.fileExists(fileName), hasInvalidatedResolutions, hasInvalidatedLibResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) {
|
||||
compilerHost = undefined;
|
||||
parsedCommandLines = undefined;
|
||||
releasedScriptKinds = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1738,6 +1742,7 @@ export function createLanguageService(
|
||||
// After this point, the cache needs to be cleared to allow all collected snapshots to be released
|
||||
compilerHost = undefined;
|
||||
parsedCommandLines = undefined;
|
||||
releasedScriptKinds = undefined;
|
||||
|
||||
// We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above,
|
||||
// Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during
|
||||
@ -1841,12 +1846,13 @@ export function createLanguageService(
|
||||
// We do not support the scenario where a host can modify a registered
|
||||
// file's script kind, i.e. in one project some file is treated as ".ts"
|
||||
// and in another as ".js"
|
||||
if (scriptKind === oldSourceFile.scriptKind) {
|
||||
if (scriptKind === oldSourceFile.scriptKind || releasedScriptKinds!.has(oldSourceFile.resolvedPath)) {
|
||||
return documentRegistry.updateDocumentWithKey(fileName, path, host, documentRegistryBucketKey, scriptSnapshot, scriptVersion, scriptKind, languageVersionOrOptions);
|
||||
}
|
||||
else {
|
||||
// Release old source file and fall through to aquire new file with new script kind
|
||||
documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, documentRegistry.getKeyForCompilationSettings(program.getCompilerOptions()), oldSourceFile.scriptKind, oldSourceFile.impliedNodeFormat);
|
||||
releasedScriptKinds!.add(oldSourceFile.resolvedPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createLoggerWithInMemoryLogs,
|
||||
createProjectService,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestProjectService,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@ -103,3 +106,39 @@ describe("unittests:: tsserver:: documentRegistry:: document registry in project
|
||||
baselineTsserverLogs("documentRegistry", "Caches the source file if script info is orphan, and orphan script info changes", service);
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: documentRegistry:: works when reusing orphan script info with different scriptKind", () => {
|
||||
it("works when reusing orphan script info with different scriptKind", () => {
|
||||
const host = createServerHost({});
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const newText = "exrpot const x = 10;";
|
||||
const content = `import x from 'react';\n${newText}`;
|
||||
openFilesForSession([
|
||||
{ file: "^/inmemory/model/6", content, scriptKindName: "TSX", projectRootPath: "/users/user/projects/san" },
|
||||
{ file: "^/inmemory/model/4", content, scriptKindName: "TSX", projectRootPath: "/users/user/projects/san" },
|
||||
], session);
|
||||
closeFilesForSession(["^/inmemory/model/4"], session);
|
||||
session.executeCommandSeq<ts.server.protocol.UpdateOpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.UpdateOpen,
|
||||
arguments: {
|
||||
changedFiles: [{
|
||||
fileName: "^/inmemory/model/6",
|
||||
textChanges: [{
|
||||
newText,
|
||||
start: { line: 1, offset: 1 },
|
||||
end: { line: 2, offset: newText.length + 1 } // Remove the import so that structure is not reused
|
||||
}]
|
||||
}],
|
||||
openFiles: [
|
||||
{
|
||||
file: "^/inmemory/model/4",
|
||||
fileContent: newText,
|
||||
projectRootPath: "/users/user/projects/san", // Add same document with different script kind
|
||||
scriptKindName: "TS"
|
||||
},
|
||||
]
|
||||
}
|
||||
});
|
||||
baselineTsserverLogs("documentRegistry", "works when reusing orphan script info with different scriptKind", session);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,203 @@
|
||||
currentDirectory:: / useCaseSensitiveFileNames: false
|
||||
Info seq [hh:mm:ss:mss] Provided types map file "/a/lib/typesMap.json" doesn't exist
|
||||
Before request
|
||||
|
||||
Info seq [hh:mm:ss:mss] request:
|
||||
{
|
||||
"command": "open",
|
||||
"arguments": {
|
||||
"file": "^/inmemory/model/6",
|
||||
"projectRootPath": "/users/user/projects/san",
|
||||
"fileContent": "import x from 'react';\nexrpot const x = 10;",
|
||||
"scriptKindName": "TSX"
|
||||
},
|
||||
"seq": 1,
|
||||
"type": "request"
|
||||
}
|
||||
Info seq [hh:mm:ss:mss] Search path: ^/inmemory/model
|
||||
Info seq [hh:mm:ss:mss] For info: ^/inmemory/model/6 :: No config files found.
|
||||
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
|
||||
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/^ 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
|
||||
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/^ 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
|
||||
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
|
||||
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
|
||||
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
|
||||
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Failed Lookup Locations
|
||||
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /dev/null/inferredProject1* WatchType: Missing file
|
||||
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
|
||||
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/san/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
|
||||
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
|
||||
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /users/user/projects/node_modules/@types 1 undefined Project: /dev/null/inferredProject1* WatchType: Type roots
|
||||
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* Version: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms
|
||||
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
|
||||
Info seq [hh:mm:ss:mss] Files (1)
|
||||
^/inmemory/model/6 SVC-1-0 "import x from 'react';\nexrpot const x = 10;"
|
||||
|
||||
|
||||
^/inmemory/model/6
|
||||
Root file specified for compilation
|
||||
|
||||
Info seq [hh:mm:ss:mss] -----------------------------------------------
|
||||
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
|
||||
Info seq [hh:mm:ss:mss] Files (1)
|
||||
|
||||
Info seq [hh:mm:ss:mss] -----------------------------------------------
|
||||
Info seq [hh:mm:ss:mss] Open files:
|
||||
Info seq [hh:mm:ss:mss] FileName: ^/inmemory/model/6 ProjectRootPath: /users/user/projects/san
|
||||
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject1*
|
||||
Info seq [hh:mm:ss:mss] response:
|
||||
{
|
||||
"responseRequired": false
|
||||
}
|
||||
After request
|
||||
|
||||
PolledWatches::
|
||||
/a/lib/lib.d.ts: *new*
|
||||
{"pollingInterval":500}
|
||||
/users/user/projects/node_modules: *new*
|
||||
{"pollingInterval":500}
|
||||
/users/user/projects/node_modules/@types: *new*
|
||||
{"pollingInterval":500}
|
||||
/users/user/projects/san/^: *new*
|
||||
{"pollingInterval":500}
|
||||
/users/user/projects/san/node_modules: *new*
|
||||
{"pollingInterval":500}
|
||||
/users/user/projects/san/node_modules/@types: *new*
|
||||
{"pollingInterval":500}
|
||||
|
||||
Before request
|
||||
|
||||
Info seq [hh:mm:ss:mss] request:
|
||||
{
|
||||
"command": "open",
|
||||
"arguments": {
|
||||
"file": "^/inmemory/model/4",
|
||||
"projectRootPath": "/users/user/projects/san",
|
||||
"fileContent": "import x from 'react';\nexrpot const x = 10;",
|
||||
"scriptKindName": "TSX"
|
||||
},
|
||||
"seq": 2,
|
||||
"type": "request"
|
||||
}
|
||||
Info seq [hh:mm:ss:mss] Search path: ^/inmemory/model
|
||||
Info seq [hh:mm:ss:mss] For info: ^/inmemory/model/4 :: No config files found.
|
||||
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
|
||||
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* Version: 2 structureChanged: true structureIsReused:: Not Elapsed:: *ms
|
||||
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
|
||||
Info seq [hh:mm:ss:mss] Files (2)
|
||||
^/inmemory/model/6 SVC-1-0 "import x from 'react';\nexrpot const x = 10;"
|
||||
^/inmemory/model/4 SVC-1-0 "import x from 'react';\nexrpot const x = 10;"
|
||||
|
||||
|
||||
^/inmemory/model/6
|
||||
Root file specified for compilation
|
||||
^/inmemory/model/4
|
||||
Root file specified for compilation
|
||||
|
||||
Info seq [hh:mm:ss:mss] -----------------------------------------------
|
||||
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
|
||||
Info seq [hh:mm:ss:mss] Files (2)
|
||||
|
||||
Info seq [hh:mm:ss:mss] -----------------------------------------------
|
||||
Info seq [hh:mm:ss:mss] Open files:
|
||||
Info seq [hh:mm:ss:mss] FileName: ^/inmemory/model/6 ProjectRootPath: /users/user/projects/san
|
||||
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject1*
|
||||
Info seq [hh:mm:ss:mss] FileName: ^/inmemory/model/4 ProjectRootPath: /users/user/projects/san
|
||||
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject1*
|
||||
Info seq [hh:mm:ss:mss] response:
|
||||
{
|
||||
"responseRequired": false
|
||||
}
|
||||
After request
|
||||
|
||||
Before request
|
||||
|
||||
Info seq [hh:mm:ss:mss] request:
|
||||
{
|
||||
"command": "close",
|
||||
"arguments": {
|
||||
"file": "^/inmemory/model/4"
|
||||
},
|
||||
"seq": 3,
|
||||
"type": "request"
|
||||
}
|
||||
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
|
||||
Info seq [hh:mm:ss:mss] Files (2)
|
||||
|
||||
Info seq [hh:mm:ss:mss] -----------------------------------------------
|
||||
Info seq [hh:mm:ss:mss] Open files:
|
||||
Info seq [hh:mm:ss:mss] FileName: ^/inmemory/model/6 ProjectRootPath: /users/user/projects/san
|
||||
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject1*
|
||||
Info seq [hh:mm:ss:mss] response:
|
||||
{
|
||||
"responseRequired": false
|
||||
}
|
||||
After request
|
||||
|
||||
Before request
|
||||
|
||||
Info seq [hh:mm:ss:mss] request:
|
||||
{
|
||||
"command": "updateOpen",
|
||||
"arguments": {
|
||||
"changedFiles": [
|
||||
{
|
||||
"fileName": "^/inmemory/model/6",
|
||||
"textChanges": [
|
||||
{
|
||||
"newText": "exrpot const x = 10;",
|
||||
"start": {
|
||||
"line": 1,
|
||||
"offset": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"offset": 21
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"openFiles": [
|
||||
{
|
||||
"file": "^/inmemory/model/4",
|
||||
"fileContent": "exrpot const x = 10;",
|
||||
"projectRootPath": "/users/user/projects/san",
|
||||
"scriptKindName": "TS"
|
||||
}
|
||||
]
|
||||
},
|
||||
"seq": 4,
|
||||
"type": "request"
|
||||
}
|
||||
Info seq [hh:mm:ss:mss] Search path: ^/inmemory/model
|
||||
Info seq [hh:mm:ss:mss] For info: ^/inmemory/model/4 :: No config files found.
|
||||
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
|
||||
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* Version: 3 structureChanged: true structureIsReused:: SafeModules Elapsed:: *ms
|
||||
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
|
||||
Info seq [hh:mm:ss:mss] Files (2)
|
||||
^/inmemory/model/6 SVC-1-1 "exrpot const x = 10;"
|
||||
^/inmemory/model/4 SVC-2-0 "exrpot const x = 10;"
|
||||
|
||||
|
||||
^/inmemory/model/6
|
||||
Root file specified for compilation
|
||||
^/inmemory/model/4
|
||||
Root file specified for compilation
|
||||
|
||||
Info seq [hh:mm:ss:mss] -----------------------------------------------
|
||||
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
|
||||
Info seq [hh:mm:ss:mss] Files (2)
|
||||
|
||||
Info seq [hh:mm:ss:mss] -----------------------------------------------
|
||||
Info seq [hh:mm:ss:mss] Open files:
|
||||
Info seq [hh:mm:ss:mss] FileName: ^/inmemory/model/6 ProjectRootPath: /users/user/projects/san
|
||||
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject1*
|
||||
Info seq [hh:mm:ss:mss] FileName: ^/inmemory/model/4 ProjectRootPath: /users/user/projects/san
|
||||
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject1*
|
||||
Info seq [hh:mm:ss:mss] response:
|
||||
{
|
||||
"response": true,
|
||||
"responseRequired": true
|
||||
}
|
||||
After request
|
||||
Loading…
x
Reference in New Issue
Block a user