- fix plugin chaining

If we have plugins that are ordered before typescript, e.g. `replace`,
the input to typescript should be the output of the previous plugin.
However, this doesn't happen, instead typescript transforms the original
file.

From my (possibly incorrect) analysis, this happens because of a cache
invalidation issue. If a module is processed by typescript before it is
transformed by the plugin, it seems the file is read directly from the
disk and inserted into the LanguageService `HostCache`. Later, when the
file is transformed by the plugin, there is a call to `setSnapshot` with
the "good" code (transformed by previous plugins), and then a call to
`getEmitOutput` which is expected to use the snapshot we had just set.
But this does *not* happen, instead we get the "bad" code from the
`HostCache`.

To fix this, make each call to `setSnapshot` increment the "script
version"; this tells typescript that it needs to reprocess the file.
This commit is contained in:
Ran Benita 2017-03-09 22:04:23 +02:00
parent e06785ffdd
commit 01958a4fce

View File

@ -6,6 +6,7 @@ export class LanguageServiceHost implements ts.LanguageServiceHost
{
private cwd = process.cwd();
private snapshots: { [fileName: string]: ts.IScriptSnapshot } = {};
private versions: { [fileName: string]: number } = {};
constructor(private parsedConfig: ts.ParsedCommandLine)
{
@ -15,6 +16,7 @@ export class LanguageServiceHost implements ts.LanguageServiceHost
{
let snapshot = ts.ScriptSnapshot.fromString(data);
this.snapshots[fileName] = snapshot;
this.versions[fileName] = (this.versions[fileName] || 0) + 1;
return snapshot;
}
@ -39,7 +41,7 @@ export class LanguageServiceHost implements ts.LanguageServiceHost
public getScriptVersion(_fileName: string)
{
return "0";
return (this.versions[_fileName] || 0).toString();
}
public getScriptFileNames()