--emitDeclarationsOnly flag to enable declarations only output (#20735)

* Add emitOnlyDeclarations flag

* Fix name

* verifyOptions checking logic

* Passing tests

* doJsEmitBaseline

* Tests !!!
This commit is contained in:
Manoj Patel 2018-01-25 15:35:18 -08:00 committed by Mohamed Hegazy
parent 7c4e755eff
commit afc588eb9e
20 changed files with 186 additions and 5 deletions

View file

@ -186,6 +186,12 @@ namespace ts {
category: Diagnostics.Basic_Options,
description: Diagnostics.Generates_corresponding_d_ts_file,
},
{
name: "emitDeclarationsOnly",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Only_emit_d_ts_declaration_files,
},
{
name: "sourceMap",
type: "boolean",

View file

@ -2807,6 +2807,10 @@
"category": "Message",
"code": 6013
},
"Only emit '.d.ts' declaration files.": {
"category": "Message",
"code": 6014
},
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'.": {
"category": "Message",
"code": 6015

View file

@ -135,7 +135,7 @@ namespace ts {
function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
// Make sure not to write js file and source map file if any of them cannot be written
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) {
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit && !compilerOptions.emitDeclarationsOnly) {
if (!emitOnlyDtsFiles) {
printSourceFileOrBundle(jsFilePath, sourceMapFilePath, sourceFileOrBundle);
}

View file

@ -2201,6 +2201,16 @@ namespace ts {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs"));
}
if (options.emitDeclarationsOnly) {
if (!options.declaration) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDeclarationsOnly", "declarations");
}
if (options.noEmit) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationsOnly", "noEmit");
}
}
if (options.emitDecoratorMetadata &&
!options.experimentalDecorators) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators");
@ -2223,7 +2233,9 @@ namespace ts {
const emitHost = getEmitHost();
const emitFilesSeen = createMap<true>();
forEachEmittedFile(emitHost, (emitFileNames) => {
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
if (!options.emitDeclarationsOnly) {
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
}
verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen);
});
}

View file

@ -3967,6 +3967,7 @@ namespace ts {
/** configFile is set as non enumerable property so as to avoid checking of json source files */
/* @internal */ readonly configFile?: JsonSourceFile;
declaration?: boolean;
emitDeclarationsOnly?: boolean;
declarationDir?: string;
/* @internal */ diagnostics?: boolean;
/* @internal */ extendedDiagnostics?: boolean;

View file

@ -1252,8 +1252,18 @@ namespace Harness {
options: ts.CompilerOptions,
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
currentDirectory: string): DeclarationCompilationContext | undefined {
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
throw new Error("There were no errors and declFiles generated did not match number of js files generated");
if (result.errors.length === 0) {
if (options.declaration) {
if (options.emitDeclarationsOnly) {
if (result.files.length > 0 || result.declFilesCode.length === 0) {
throw new Error("Only declaration files should be generated when emitDeclarationsOnly:true");
}
}
else if (result.declFilesCode.length !== result.files.length) {
throw new Error("There were no errors and declFiles generated did not match number of js files generated");
}
}
}
const declInputFiles: TestFile[] = [];
@ -1654,7 +1664,7 @@ namespace Harness {
}
export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompilerResult, tsConfigFiles: Harness.Compiler.TestFile[], toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], harnessSettings: Harness.TestCaseParser.CompilerSettings) {
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
if (!options.noEmit && !options.emitDeclarationsOnly && result.files.length === 0 && result.errors.length === 0) {
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
}

View file

@ -2266,6 +2266,7 @@ declare namespace ts {
charset?: string;
checkJs?: boolean;
declaration?: boolean;
emitDeclarationsOnly?: boolean;
declarationDir?: string;
disableSizeLimit?: boolean;
downlevelIteration?: boolean;

View file

@ -2266,6 +2266,7 @@ declare namespace ts {
charset?: string;
checkJs?: boolean;
declaration?: boolean;
emitDeclarationsOnly?: boolean;
declarationDir?: string;
disableSizeLimit?: boolean;
downlevelIteration?: boolean;

View file

@ -0,0 +1,26 @@
//// [helloworld.ts]
const Log = {
info(msg: string) {}
}
class HelloWorld {
constructor(private name: string) {
}
public hello() {
Log.info(`Hello ${this.name}`);
}
}
//// [helloworld.d.ts]
declare const Log: {
info(msg: string): void;
};
declare class HelloWorld {
private name;
constructor(name: string);
hello(): void;
}

View file

@ -0,0 +1,29 @@
=== tests/cases/compiler/helloworld.ts ===
const Log = {
>Log : Symbol(Log, Decl(helloworld.ts, 0, 5))
info(msg: string) {}
>info : Symbol(info, Decl(helloworld.ts, 0, 13))
>msg : Symbol(msg, Decl(helloworld.ts, 1, 7))
}
class HelloWorld {
>HelloWorld : Symbol(HelloWorld, Decl(helloworld.ts, 2, 1))
constructor(private name: string) {
>name : Symbol(HelloWorld.name, Decl(helloworld.ts, 5, 14))
}
public hello() {
>hello : Symbol(HelloWorld.hello, Decl(helloworld.ts, 6, 3))
Log.info(`Hello ${this.name}`);
>Log.info : Symbol(info, Decl(helloworld.ts, 0, 13))
>Log : Symbol(Log, Decl(helloworld.ts, 0, 5))
>info : Symbol(info, Decl(helloworld.ts, 0, 13))
>this.name : Symbol(HelloWorld.name, Decl(helloworld.ts, 5, 14))
>this : Symbol(HelloWorld, Decl(helloworld.ts, 2, 1))
>name : Symbol(HelloWorld.name, Decl(helloworld.ts, 5, 14))
}
}

View file

@ -0,0 +1,32 @@
=== tests/cases/compiler/helloworld.ts ===
const Log = {
>Log : { info(msg: string): void; }
>{ info(msg: string) {}} : { info(msg: string): void; }
info(msg: string) {}
>info : (msg: string) => void
>msg : string
}
class HelloWorld {
>HelloWorld : HelloWorld
constructor(private name: string) {
>name : string
}
public hello() {
>hello : () => void
Log.info(`Hello ${this.name}`);
>Log.info(`Hello ${this.name}`) : void
>Log.info : (msg: string) => void
>Log : { info(msg: string): void; }
>info : (msg: string) => void
>`Hello ${this.name}` : string
>this.name : string
>this : this
>name : string
}
}

View file

@ -0,0 +1,7 @@
error TS5052: Option 'emitDeclarationsOnly' cannot be specified without specifying option 'declarations'.
!!! error TS5052: Option 'emitDeclarationsOnly' cannot be specified without specifying option 'declarations'.
==== tests/cases/compiler/hello.ts (0 errors) ====
var hello = "yo!";

View file

@ -0,0 +1,4 @@
=== tests/cases/compiler/hello.ts ===
var hello = "yo!";
>hello : Symbol(hello, Decl(hello.ts, 0, 3))

View file

@ -0,0 +1,5 @@
=== tests/cases/compiler/hello.ts ===
var hello = "yo!";
>hello : string
>"yo!" : "yo!"

View file

@ -0,0 +1,9 @@
error TS5052: Option 'emitDeclarationsOnly' cannot be specified without specifying option 'declarations'.
error TS5053: Option 'emitDeclarationsOnly' cannot be specified with option 'noEmit'.
!!! error TS5052: Option 'emitDeclarationsOnly' cannot be specified without specifying option 'declarations'.
!!! error TS5053: Option 'emitDeclarationsOnly' cannot be specified with option 'noEmit'.
==== tests/cases/compiler/hello.ts (0 errors) ====
var hello = "yo!";

View file

@ -0,0 +1,4 @@
=== tests/cases/compiler/hello.ts ===
var hello = "yo!";
>hello : Symbol(hello, Decl(hello.ts, 0, 3))

View file

@ -0,0 +1,5 @@
=== tests/cases/compiler/hello.ts ===
var hello = "yo!";
>hello : string
>"yo!" : "yo!"

View file

@ -0,0 +1,16 @@
// @declaration: true
// @emitDeclarationsOnly: true
// @filename: helloworld.ts
const Log = {
info(msg: string) {}
}
class HelloWorld {
constructor(private name: string) {
}
public hello() {
Log.info(`Hello ${this.name}`);
}
}

View file

@ -0,0 +1,4 @@
// @emitDeclarationsOnly: true
// @filename: hello.ts
var hello = "yo!";

View file

@ -0,0 +1,5 @@
// @noEmit: true
// @emitDeclarationsOnly: true
// @filename: hello.ts
var hello = "yo!";