-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Reuse program structure #3616
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
Reuse program structure #3616
Changes from 5 commits
226deec
39e832d
7a7d775
ba3eb0d
16deccd
9e81ac9
df508de
c968b36
66f6736
2685d40
6a502cd
e15c700
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1176,8 +1176,11 @@ namespace ts { | |
// Stores a line map for the file. | ||
// This field should never be used directly to obtain line map, use getLineMap function instead. | ||
/* @internal */ lineMap: number[]; | ||
|
||
/* @internal */ classifiableNames?: Map<string>; | ||
// Stores a mapping 'external module reference text' -> 'resolved file name' | undefined | ||
// Content of this fiels should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead | ||
/* @internal */ resolvedModules: Map<string>; | ||
/* @internal */ imports: LiteralExpression[]; | ||
} | ||
|
||
export interface ScriptReferenceHost { | ||
|
@@ -1195,6 +1198,12 @@ namespace ts { | |
} | ||
|
||
export interface Program extends ScriptReferenceHost { | ||
|
||
/** | ||
* Get a list of root file names that were passed to a 'createProgram' | ||
*/ | ||
getRootFileNames(): string[] | ||
|
||
/** | ||
* Get a list of files in the program | ||
*/ | ||
|
@@ -1235,6 +1244,7 @@ namespace ts { | |
/* @internal */ getIdentifierCount(): number; | ||
/* @internal */ getSymbolCount(): number; | ||
/* @internal */ getTypeCount(): number; | ||
/* @internal */ structureIsReused?: boolean; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment that this is for tests ony. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
} | ||
|
||
export interface SourceMapSpan { | ||
|
@@ -1881,7 +1891,7 @@ namespace ts { | |
CarriageReturnLineFeed = 0, | ||
LineFeed = 1, | ||
} | ||
export interface LineAndCharacter { | ||
line: number; | ||
/* | ||
|
@@ -2065,6 +2075,7 @@ namespace ts { | |
getCanonicalFileName(fileName: string): string; | ||
useCaseSensitiveFileNames(): boolean; | ||
getNewLine(): string; | ||
hasChanges?(oldFile: SourceFile): boolean; | ||
} | ||
|
||
export interface TextSpan { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,6 +78,40 @@ namespace ts { | |
return node.end - node.pos; | ||
} | ||
|
||
export function arrayIsEqualTo<T>(arr1: T[], arr2: T[], comparer: (a: T, b: T) => boolean): boolean { | ||
if (!arr1 || !arr2) { | ||
return arr1 === arr2; | ||
} | ||
|
||
if (arr1.length !== arr2.length) { | ||
return false; | ||
} | ||
|
||
for (let i = 0; i < arr1.length; ++i) { | ||
if (!comparer(arr1[i], arr2[i])) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
export function hasResolvedModuleName(sourceFile: SourceFile, moduleName: LiteralExpression): boolean { | ||
return sourceFile.resolvedModules && hasProperty(sourceFile.resolvedModules, moduleName.text); | ||
} | ||
|
||
export function getResolvedModuleFileName(sourceFile: SourceFile, moduleName: LiteralExpression): string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can we make this take moduleNameText instead of a node, this way it is easier to understand the logic looking at the call. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
return sourceFile.resolvedModules && sourceFile.resolvedModules[moduleName.text]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should not this be hasOwnProperty to avoid modulename looks for something like "toString". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. never mind. noticed that we are using |
||
} | ||
|
||
export function setResolvedModuleName(sourceFile: SourceFile, moduleName: LiteralExpression, resolvedFileName: string): void { | ||
if (!sourceFile.resolvedModules) { | ||
sourceFile.resolvedModules = {}; | ||
} | ||
|
||
sourceFile.resolvedModules[moduleName.text] = resolvedFileName; | ||
} | ||
|
||
// Returns true if this node contains a parse error anywhere underneath it. | ||
export function containsParseError(node: Node): boolean { | ||
aggregateChildData(node); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -753,7 +753,8 @@ namespace ts { | |
public languageVersion: ScriptTarget; | ||
public identifiers: Map<string>; | ||
public nameTable: Map<string>; | ||
|
||
public resolvedModules: Map<string>; | ||
public imports: LiteralExpression[]; | ||
private namedDeclarations: Map<Declaration[]>; | ||
|
||
public update(newText: string, textChangeRange: TextChangeRange): SourceFile { | ||
|
@@ -2471,6 +2472,8 @@ namespace ts { | |
let newSettings = hostCache.compilationSettings(); | ||
let changesInCompilationSettingsAffectSyntax = oldSettings && oldSettings.target !== newSettings.target; | ||
|
||
let reusableOldProgram = changesInCompilationSettingsAffectSyntax ? undefined : program; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can move the target check to create program right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure |
||
|
||
// Now create a new compiler | ||
let newProgram = createProgram(hostCache.getRootFileNames(), newSettings, { | ||
getSourceFile: getOrCreateSourceFile, | ||
|
@@ -2480,8 +2483,9 @@ namespace ts { | |
getNewLine: () => host.getNewLine ? host.getNewLine() : "\r\n", | ||
getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), | ||
writeFile: (fileName, data, writeByteOrderMark) => { }, | ||
getCurrentDirectory: () => host.getCurrentDirectory() | ||
}); | ||
getCurrentDirectory: () => host.getCurrentDirectory(), | ||
hasChanges: oldFile => oldFile.version !== hostCache.getVersion(oldFile.fileName) | ||
}, reusableOldProgram); | ||
|
||
// Release any files we have acquired in the old program but are | ||
// not part of the new program. | ||
|
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.
unnecessary change, will remove it from the PR