-
Notifications
You must be signed in to change notification settings - Fork 13k
Reuse Module Resolutions from Unchanged Files #15261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… it specified Fixes microsoft#13910
Previously it assumed valueDeclaration was present, which is not true for type aliases.
Previously it crashed when it assumed valueDeclaration was always defined.
Remove unused file
…rst-decl-not-valueDecl mergeSymbol uses first declaration, not valueDeclaration
Use base tsconfig's compileOnSave option if tsconfig.json doesnt have it specified
src/compiler/program.ts
Outdated
None = 0, | ||
NoOldProgram = 1, | ||
ModuleResolutionOptions = 2, | ||
RootNames = 3, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 << 3
, etc
src/compiler/program.ts
Outdated
|
||
for (const oldSourceFile of oldProgram.getSourceFiles()) { | ||
let newSourceFile = host.getSourceFileByPath | ||
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target) | ||
: host.getSourceFile(oldSourceFile.fileName, options.target); | ||
|
||
if (!newSourceFile) { | ||
return false; | ||
structuralChanges |= StructuralChangesFromOldProgram.SourceFileRemoved; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SourceFileRemoved is in your CannotReuseResolution
set, so why collect flags and continue here rather than just return?
src/compiler/program.ts
Outdated
return false; | ||
else { | ||
// file has no changes - use it as is | ||
newSourceFile = oldSourceFile; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit hard to tell in this diff... but is this in the else clause to if (oldSourceFile !== newSourceFile)
? If so, this statement seems like a no-op.
src/compiler/types.ts
Outdated
/* @internal */ structureIsReused?: StructureIsReused; | ||
} | ||
|
||
export const enum StructureIsReused { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/* @internal */
src/compiler/program.ts
Outdated
if (!oldProgramState && !file.ambientModuleNames.length) { | ||
// if old program state is not supplied and file does not contain locally defined ambient modules | ||
// then the best we can do is fallback to the default logic | ||
function createOldProgramState( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just inline that. no need to call a function that just wraps the arguments in a literal.
src/compiler/program.ts
Outdated
@@ -6,6 +6,23 @@ namespace ts { | |||
const emptyArray: any[] = []; | |||
const ignoreDiagnosticCommentRegEx = /(^\s*$)|(^\s*\/\/\/?\s*(@ts-ignore)?)/; | |||
|
|||
|
|||
const enum StructuralChangesFromOldProgram { | |||
None = 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's keep this as a tri-state enum
src/compiler/program.ts
Outdated
// ensure that module resolution results are still correct | ||
const resolutionsChanged = hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, moduleResolutionIsEqualTo); | ||
if (resolutionsChanged) { | ||
return false; | ||
return StructuralChangesFromOldProgram.Imports | StructuralChangesFromOldProgram.ModuleAugmentations; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you want to continue here instead of return to allow for copying the state of unchanged files.
src/compiler/program.ts
Outdated
// - in the old program module name was resolved to ambient module whose declaration is in non-modified file | ||
// TODO: if we want to reuse resolutions more aggressively, refine this to check for whether the | ||
// text of the corresponding modulenames has changed. | ||
if (file === oldSourceFile) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a test for the npm install
case:
file1.ts
=>import * as a from "a";
- semantic errors
- Add new file
node_modules\a\index.d.ts
- make an edit in
file2.ts
- no semantic errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
src/compiler/program.ts
Outdated
|
||
// there is an old program, check if we can reuse its structure | ||
const oldRootNames = oldProgram.getRootFileNames(); | ||
if (!arrayIsEqualTo(oldRootNames, rootNames)) { | ||
return false; | ||
oldProgram.structureIsReused = StructureIsReused.Not; | ||
return StructureIsReused.Not; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return oldProgram.structureIsReused = StructureIsReused.Not;
src/compiler/program.ts
Outdated
} | ||
|
||
if (!arrayIsEqualTo(options.types, oldOptions.types)) { | ||
return false; | ||
oldProgram.structureIsReused = StructureIsReused.Not; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return oldProgram.structureIsReused = StructureIsReused.Not;
src/compiler/types.ts
Outdated
|
||
/* @internal */ | ||
export const enum StructureIsReused { | ||
Completely, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Start at 1 or make Not
=== 0
src/compiler/utilities.ts
Outdated
@@ -123,7 +123,7 @@ namespace ts { | |||
/* @internal */ | |||
export function hasChangesInResolutions<T>(names: string[], newResolutions: T[], oldResolutions: Map<T>, comparer: (oldResolution: T, newResolution: T) => boolean): boolean { | |||
if (names.length !== newResolutions.length) { | |||
return false; | |||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Figure out how to hit this in a test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(or change to an assert)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hasChangesInResolutions
is called on resolutions obtained from resolveModuleNamesReusingOldState
and resolveTypeReferenceDirectiveNamesWorker
.
Both guarantee in their implementations that the array they return is the same length as names
.
Changing to an assert.
src/compiler/diagnosticMessages.json
Outdated
}, | ||
"Reusing resolution of module '{0}' to file '{1}' from old program.": { | ||
"category": "Message", | ||
"code": 618 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean 618 here? Seems kind low ;-)
src/compiler/program.ts
Outdated
if (!oldProgramState) { | ||
return false; | ||
} | ||
// TODO: if we change our policy of rechecking failed lookups on each program create, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nit: But some of the TODO comments aren't really TODOs (in the sense that work is incomplete), but just a note for any future changes. Just remove the "TODO: " from these if there is no work still to do.
This fix is intended to speedup typing in
import
statements.Fixes the following VS community issues:
https://developercommunity.visualstudio.com/content/problem/29920/vs-2017-is-hanging-for-a-a-few-seconds-when-i-add.html
https://developercommunity.visualstudio.com/content/problem/3317/vs-typescript-editor-hanging-while-im-typing-the-p.html