Printer API unit tests

This commit is contained in:
Ron Buckton
2017-01-30 13:40:42 -08:00
parent 0165b71549
commit f0563ac287
11 changed files with 173 additions and 52 deletions

View File

@@ -269,6 +269,7 @@ var harnessSources = harnessCoreSources.concat([
"projectErrors.ts",
"matchFiles.ts",
"initializeTSConfig.ts",
"printer.ts",
].map(function (f) {
return path.join(unittestsDirectory, f);
})).concat([

View File

@@ -1451,7 +1451,7 @@ namespace ts {
return compilerOptions.target || ScriptTarget.ES3;
}
export function getEmitModuleKind(compilerOptions: CompilerOptions | PrinterOptions) {
export function getEmitModuleKind(compilerOptions: CompilerOptions) {
return typeof compilerOptions.module === "number" ?
compilerOptions.module :
getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 ? ModuleKind.ES2015 : ModuleKind.CommonJS;

View File

@@ -12,6 +12,7 @@ namespace ts {
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult {
const compilerOptions = host.getCompilerOptions();
const moduleKind = getEmitModuleKind(compilerOptions);
const sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined;
const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined;
const emitterDiagnostics = createDiagnosticCollection();
@@ -147,6 +148,10 @@ namespace ts {
function emitHelpers(node: Node, writeLines: (text: string) => void) {
let helpersEmitted = false;
const bundle = node.kind === SyntaxKind.Bundle ? <Bundle>node : undefined;
if (bundle && moduleKind === ModuleKind.None) {
return;
}
const numNodes = bundle ? bundle.sourceFiles.length : 1;
for (let i = 0; i < numNodes; i++) {
const currentNode = bundle ? bundle.sourceFiles[i] : node;
@@ -201,7 +206,6 @@ namespace ts {
const newLine = getNewLineCharacter(printerOptions);
const languageVersion = getEmitScriptTarget(printerOptions);
const moduleKind = getEmitModuleKind(printerOptions);
const comments = createCommentWriter(printerOptions, onEmitSourceMapOfPosition);
const {
emitNodeWithComments,
@@ -257,9 +261,7 @@ namespace ts {
function writeBundle(bundle: Bundle, output: EmitTextWriter) {
const previousWriter = writer;
setWriter(output);
if (moduleKind) {
emitHelpersIndirect(bundle);
}
emitHelpersIndirect(bundle);
for (const sourceFile of bundle.sourceFiles) {
print(EmitHint.SourceFile, sourceFile, sourceFile);
}
@@ -280,11 +282,8 @@ namespace ts {
}
function endPrint() {
const text = writer.getText();
if (writer === ownWriter) {
writer.reset();
}
const text = ownWriter.getText();
ownWriter.reset();
return text;
}
@@ -385,6 +384,15 @@ namespace ts {
function pipelineEmitUnspecified(node: Node): void {
const kind = node.kind;
// Reserved words
// Strict mode reserved words
// Contextual keywords
if (isKeyword(kind)) {
writeTokenText(kind);
return;
}
switch (kind) {
// Pseudo-literals
case SyntaxKind.TemplateHead:
@@ -396,46 +404,6 @@ namespace ts {
case SyntaxKind.Identifier:
return emitIdentifier(<Identifier>node);
// Reserved words
case SyntaxKind.ConstKeyword:
case SyntaxKind.DefaultKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.VoidKeyword:
// Strict mode reserved words
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.StaticKeyword:
// Contextual keywords
case SyntaxKind.AbstractKeyword:
case SyntaxKind.AsKeyword:
case SyntaxKind.AnyKeyword:
case SyntaxKind.AsyncKeyword:
case SyntaxKind.AwaitKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.ConstructorKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.GetKeyword:
case SyntaxKind.IsKeyword:
case SyntaxKind.ModuleKeyword:
case SyntaxKind.NamespaceKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.ReadonlyKeyword:
case SyntaxKind.RequireKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.SetKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.TypeKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.FromKeyword:
case SyntaxKind.GlobalKeyword:
case SyntaxKind.OfKeyword:
writeTokenText(kind);
return;
// Parse tree nodes
// Names

View File

@@ -3937,7 +3937,6 @@
export interface PrinterOptions {
target?: ScriptTarget;
module?: ModuleKind;
removeComments?: boolean;
newLine?: NewLineKind;
/*@internal*/ sourceMap?: boolean;

View File

@@ -118,6 +118,7 @@
"./unittests/initializeTSConfig.ts",
"./unittests/compileOnSave.ts",
"./unittests/typingsInstaller.ts",
"./unittests/projectErrors.ts"
"./unittests/projectErrors.ts",
"./unittests/printer.ts"
]
}

View File

@@ -0,0 +1,97 @@
/// <reference path="..\..\compiler\emitter.ts" />
/// <reference path="..\harness.ts" />
namespace ts {
describe("PrinterAPI", () => {
function makePrintsCorrectly(prefix: string) {
return function printsCorrectly(name: string, options: PrinterOptions, printCallback: (printer: Printer) => string) {
it(name, () => {
Harness.Baseline.runBaseline(`printerApi/${prefix}.${name}.js`, () =>
printCallback(createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed, ...options })));
});
}
}
describe("printFile", () => {
const printsCorrectly = makePrintsCorrectly("printsFileCorrectly");
const sourceFile = createSourceFile("source.ts", `
interface A<T> {
// comment1
readonly prop?: T;
// comment2
method(): void;
// comment3
new <T>(): A<T>;
// comment4
<T>(): A<T>;
}
// comment5
type B = number | string | object;
type C = A<number> & { x: string; }; // comment6
// comment7
enum E1 {
// comment8
first
}
const enum E2 {
second
}
// comment9
console.log(1 + 2);
`, ScriptTarget.ES2015);
printsCorrectly("default", {}, printer => printer.printFile(sourceFile));
printsCorrectly("removeComments", { removeComments: true }, printer => printer.printFile(sourceFile));
});
describe("printBundle", () => {
const printsCorrectly = makePrintsCorrectly("printsBundleCorrectly");
const bundle = createBundle([
createSourceFile("a.ts", `
/*! [a.ts] */
// comment0
const a = 1;
`, ScriptTarget.ES2015),
createSourceFile("b.ts", `
/*! [b.ts] */
// comment1
const b = 2;
`, ScriptTarget.ES2015)
]);
printsCorrectly("default", {}, printer => printer.printBundle(bundle));
printsCorrectly("removeComments", { removeComments: true }, printer => printer.printBundle(bundle));
});
describe("printNode", () => {
const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly");
const sourceFile = createSourceFile("source.ts", "", ScriptTarget.ES2015);
const syntheticNode = createClassDeclaration(
undefined,
undefined,
/*name*/ createIdentifier("C"),
undefined,
undefined,
createNodeArray([
createProperty(
undefined,
createNodeArray([createToken(SyntaxKind.PublicKeyword)]),
createIdentifier("prop"),
undefined,
undefined,
undefined
)
])
);
printsCorrectly("class", {}, printer => printer.printNode(EmitHint.Unspecified, syntheticNode, sourceFile));
});
});
}

View File

@@ -0,0 +1,6 @@
/*! [a.ts] */
// comment0
const a = 1;
/*! [b.ts] */
// comment1
const b = 2;

View File

@@ -0,0 +1,4 @@
/*! [a.ts] */
const a = 1;
/*! [b.ts] */
const b = 2;

View File

@@ -0,0 +1,25 @@
interface A<T> {
// comment1
readonly prop?: T;
// comment2
method(): void;
// comment3
new <T>(): A<T>;
// comment4
<T>(): A<T>;
}
// comment5
type B = number | string | object;
type C = A<number> & {
x: string;
}; // comment6
// comment7
enum E1 {
// comment8
first
}
const enum E2 {
second
}
// comment9
console.log(1 + 2);

View File

@@ -0,0 +1,17 @@
interface A<T> {
readonly prop?: T;
method(): void;
new <T>(): A<T>;
<T>(): A<T>;
}
type B = number | string | object;
type C = A<number> & {
x: string;
};
enum E1 {
first
}
const enum E2 {
second
}
console.log(1 + 2);

View File

@@ -0,0 +1,3 @@
class C {
public prop;
}