-
Notifications
You must be signed in to change notification settings - Fork 189
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Wrap LanguageService.getEmitOutput(...).
- Loading branch information
Showing
6 changed files
with
187 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import * as ts from "typescript"; | ||
import {GlobalContainer} from "./../../../GlobalContainer"; | ||
import {Memoize} from "./../../../utils"; | ||
import {OutputFile} from "./OutputFile"; | ||
import {Diagnostic} from "./Diagnostic"; | ||
|
||
/** | ||
* Output of an emit on a single file. | ||
*/ | ||
export class EmitOutput { | ||
/** @internal */ | ||
private readonly global: GlobalContainer; | ||
/** @internal */ | ||
private readonly _compilerObject: ts.EmitOutput; | ||
/** @internal */ | ||
private readonly _diagnostics: Diagnostic[]; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
constructor(global: GlobalContainer, private readonly filePath: string, compilerObject: ts.EmitOutput) { | ||
this.global = global; | ||
this._compilerObject = compilerObject; | ||
this._diagnostics = this.compilerObject.emitSkipped ? this._getPreEmitDiagnostics() : []; | ||
} | ||
|
||
/** | ||
* TypeScript compiler emit result. | ||
*/ | ||
get compilerObject() { | ||
return this._compilerObject; | ||
} | ||
|
||
/** | ||
* Gets the diagnostics when the emit is skipped. | ||
*/ | ||
getDiagnostics() { | ||
return this._diagnostics; | ||
} | ||
|
||
/** | ||
* Gets if the emit was skipped. | ||
*/ | ||
getEmitSkipped() { | ||
return this.compilerObject.emitSkipped; | ||
} | ||
|
||
/** | ||
* Gets the output files. | ||
*/ | ||
@Memoize | ||
getOutputFiles() { | ||
return this.compilerObject.outputFiles.map(f => new OutputFile(f)); | ||
} | ||
|
||
private _getPreEmitDiagnostics() { | ||
const sourceFile = this.global.compilerFactory.getSourceFileFromFilePath(this.filePath)!; | ||
const compilerDiagnostics = ts.getPreEmitDiagnostics(this.global.program.compilerObject, sourceFile.compilerNode); | ||
return compilerDiagnostics.map(d => new Diagnostic(this.global, d)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import * as ts from "typescript"; | ||
|
||
/** | ||
* Output file of an emit. | ||
*/ | ||
export class OutputFile { | ||
/** @internal */ | ||
private readonly _compilerObject: ts.OutputFile; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
constructor(compilerObject: ts.OutputFile) { | ||
this._compilerObject = compilerObject; | ||
} | ||
|
||
/** | ||
* TypeScript compiler emit result. | ||
*/ | ||
get compilerObject() { | ||
return this._compilerObject; | ||
} | ||
|
||
/** | ||
* Gets the file name. | ||
*/ | ||
getName() { | ||
return this.compilerObject.name; | ||
} | ||
|
||
/** | ||
* Gets whether the byte order mark should be written. | ||
*/ | ||
getWriteByteOrderMark() { | ||
return this.compilerObject.writeByteOrderMark || false; | ||
} | ||
|
||
/** | ||
* Gets the file text. | ||
*/ | ||
getText() { | ||
return this.compilerObject.text; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import * as ts from "typescript"; | ||
import {expect} from "chai"; | ||
import {LanguageService, EmitOutput} from "./../../../compiler"; | ||
import {FileNotFoundError} from "./../../../errors"; | ||
import {FileUtils} from "./../../../utils"; | ||
import {getInfoFromText} from "./../testHelpers"; | ||
|
||
describe(nameof(LanguageService), () => { | ||
describe(nameof<LanguageService>(l => l.getEmitOutput), () => { | ||
function checkOutput(output: EmitOutput, expected: { emitSkipped: boolean; outputFiles: { fileName: string; text: string; writeByteOrderMark: boolean; }[]; }) { | ||
expect(output.getEmitSkipped()).to.equal(expected.emitSkipped); | ||
expect(output.getOutputFiles().length).to.equal(expected.outputFiles.length); | ||
for (let i = 0; i < expected.outputFiles.length; i++) { | ||
const actualFile = output.getOutputFiles()[i]; | ||
const expectedFile = expected.outputFiles[i]; | ||
expect(actualFile.getName()).to.equal(FileUtils.getStandardizedAbsolutePath(expectedFile.fileName)); | ||
expect(actualFile.getText()).to.equal(expectedFile.text); | ||
expect(actualFile.getWriteByteOrderMark()).to.equal(expectedFile.writeByteOrderMark); | ||
} | ||
} | ||
|
||
it("should get the emit output", () => { | ||
const {sourceFile, tsSimpleAst} = getInfoFromText("const t = 5;", { compilerOptions: { target: ts.ScriptTarget.ES5 } }); | ||
const output = sourceFile.global.languageService.getEmitOutput(sourceFile.getFilePath()); | ||
checkOutput(output, { | ||
emitSkipped: false, | ||
outputFiles: [{ | ||
fileName: sourceFile.getBaseName().replace(".ts", ".js"), | ||
text: "var t = 5;\n", | ||
writeByteOrderMark: false | ||
}] | ||
}); | ||
}); | ||
|
||
it("should only emit the declaration file when specified", () => { | ||
const {sourceFile, tsSimpleAst} = getInfoFromText("const t = 5;", { compilerOptions: { declaration: true } }); | ||
const output = sourceFile.global.languageService.getEmitOutput(sourceFile.getFilePath(), true); | ||
checkOutput(output, { | ||
emitSkipped: false, | ||
outputFiles: [{ | ||
fileName: sourceFile.getBaseName().replace(".ts", ".d.ts"), | ||
text: "declare const t = 5;\n", | ||
writeByteOrderMark: false | ||
}] | ||
}); | ||
}); | ||
|
||
it("should not emit if there is a declaraton file error", () => { | ||
const {sourceFile, tsSimpleAst} = getInfoFromText("class MyClass {}\n export class Test extends MyClass {}\n", { compilerOptions: { declaration: true } }); | ||
const output = sourceFile.global.languageService.getEmitOutput(sourceFile.getFilePath(), true); | ||
checkOutput(output, { | ||
emitSkipped: true, | ||
outputFiles: [] | ||
}); | ||
|
||
expect(output.getDiagnostics().length).to.equal(1); | ||
}); | ||
|
||
it("should throw when the specified file does not exist", () => { | ||
const {tsSimpleAst} = getInfoFromText(""); | ||
expect(() => tsSimpleAst.getLanguageService().getEmitOutput("nonExistentFile.ts")).to.throw(FileNotFoundError); | ||
}); | ||
}); | ||
}); |