Skip to content

Commit 0b06ddc

Browse files
author
Yui T
committed
Fix getEmitOutput to only output one file except when 'out' flag is specified. Add testcases
1 parent 26fbb98 commit 0b06ddc

22 files changed

+224
-319
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7183,15 +7183,7 @@ module ts {
71837183

71847184
function hasSemanticErrors() {
71857185
// Return true if there is any semantic error in a file or globally
7186-
return (getDiagnostics().length > 0) || (getGlobalDiagnostics().length > 0);
7187-
}
7188-
7189-
function shouldEmitDeclarations() {
7190-
// If the declaration emit and there are no errors being reported in program or by checker
7191-
// declarations can be emitted
7192-
return compilerOptions.declaration &&
7193-
!program.getDiagnostics().length &&
7194-
!getDiagnostics().length;
7186+
return getDiagnostics().length > 0 || getGlobalDiagnostics().length > 0;
71957187
}
71967188

71977189
function isReferencedImportDeclaration(node: ImportDeclaration): boolean {
@@ -7252,7 +7244,7 @@ module ts {
72527244
writeTypeToTextWriter(getReturnTypeOfSignature(signature), enclosingDeclaration, flags , writer);
72537245
}
72547246

7255-
function invokeEmitter() {
7247+
function invokeEmitter(targetSourceFile?: SourceFile) {
72567248
var resolver: EmitResolver = {
72577249
getProgram: () => program,
72587250
getLocalNameOfContainer: getLocalNameOfContainer,
@@ -7264,7 +7256,6 @@ module ts {
72647256
getEnumMemberValue: getEnumMemberValue,
72657257
isTopLevelValueImportedViaEntityName: isTopLevelValueImportedViaEntityName,
72667258
hasSemanticErrors: hasSemanticErrors,
7267-
shouldEmitDeclarations: shouldEmitDeclarations,
72687259
isDeclarationVisible: isDeclarationVisible,
72697260
isImplementationOfOverload: isImplementationOfOverload,
72707261
writeTypeAtLocation: writeTypeAtLocation,
@@ -7274,7 +7265,7 @@ module ts {
72747265
isImportDeclarationEntityNameReferenceDeclarationVisibile: isImportDeclarationEntityNameReferenceDeclarationVisibile
72757266
};
72767267
checkProgram();
7277-
return emitFiles(resolver);
7268+
return emitFiles(resolver, targetSourceFile);
72787269
}
72797270

72807271
function initializeTypeChecker() {

src/compiler/emitter.ts

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,21 @@ module ts {
2525
return indentStrings[1].length;
2626
}
2727

28-
export function shouldEmitToOwnFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) {
28+
export function shouldEmitToOwnFile(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean {
2929
if (!(sourceFile.flags & NodeFlags.DeclarationFile)) {
3030
if ((isExternalModule(sourceFile) || !compilerOptions.out) && !fileExtensionIs(sourceFile.filename, ".js")) {
3131
return true;
3232
}
33+
return false;
3334
}
35+
return false;
36+
}
37+
export function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) {
38+
return isExternalModule(sourceFile) || (sourceFile.flags & NodeFlags.DeclarationFile) !== 0;
3439
}
3540

36-
export function emitFiles(resolver: EmitResolver): EmitResult {
41+
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compilerOnSave feature
42+
export function emitFiles(resolver: EmitResolver, targetSourceFile?: SourceFile): EmitResult {
3743
var program = resolver.getProgram();
3844
var compilerHost = program.getCompilerHost();
3945
var compilerOptions = program.getCompilerOptions();
@@ -58,10 +64,6 @@ module ts {
5864
return emitOutputFilePathWithoutExtension + extension;
5965
}
6066

61-
function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) {
62-
return isExternalModule(sourceFile) || (sourceFile.flags & NodeFlags.DeclarationFile) !== 0;
63-
}
64-
6567
function getFirstConstructorWithBody(node: ClassDeclaration): ConstructorDeclaration {
6668
return forEach(node.members, member => {
6769
if (member.kind === SyntaxKind.Constructor && (<ConstructorDeclaration>member).body) {
@@ -3161,44 +3163,50 @@ module ts {
31613163
}
31623164
}
31633165

3164-
var shouldEmitDeclarations = resolver.shouldEmitDeclarations();
3166+
var hasSemanticErros = resolver.hasSemanticErrors();
3167+
var returnCode = EmitReturnStatus.Succeeded;
3168+
31653169
function emitFile(jsFilePath: string, sourceFile?: SourceFile) {
31663170
emitJavaScript(jsFilePath, sourceFile);
3167-
if (shouldEmitDeclarations) {
3171+
// Update the returnCode with appropriate value depended on whether we have semantic errors
3172+
if (!hasSemanticErros && compilerOptions.declaration) {
3173+
returnCode = EmitReturnStatus.Succeeded;
31683174
emitDeclarations(jsFilePath, sourceFile);
31693175
}
3176+
else if (hasSemanticErros && compilerOptions.declaration) {
3177+
returnCode = EmitReturnStatus.DeclarationGenerationSkipped;
3178+
}
3179+
else if (hasSemanticErros && !compilerOptions.declaration) {
3180+
returnCode = EmitReturnStatus.JSGeneratedWithSemanticErrors;
3181+
}
3182+
}
3183+
3184+
if (targetSourceFile === undefined) {
3185+
forEach(program.getSourceFiles(), sourceFile => {
3186+
if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
3187+
var jsFilePath = getOwnEmitOutputFilePath(sourceFile, ".js");
3188+
emitFile(jsFilePath, sourceFile);
3189+
}
3190+
});
3191+
}
3192+
else {
3193+
// Emit only one file specified in targetFilename. This is mainly used in compilerOnSave feature
3194+
var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, ".js");
3195+
emitFile(jsFilePath, targetSourceFile);
31703196
}
31713197

3172-
forEach(program.getSourceFiles(), sourceFile => {
3173-
if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
3174-
var jsFilePath = getOwnEmitOutputFilePath(sourceFile, ".js");
3175-
emitFile(jsFilePath, sourceFile);
3176-
}
3177-
});
31783198
if (compilerOptions.out) {
31793199
emitFile(compilerOptions.out);
31803200
}
3181-
3201+
31823202
// Sort and make the unique list of diagnostics
31833203
diagnostics.sort(compareDiagnostics);
31843204
diagnostics = deduplicateSortedDiagnostics(diagnostics);
31853205

3186-
var returnCode = EmitReturnStatus.Succeeded;
3187-
3188-
// Check if there is any diagnostic in an error category; if so, there is an emitter error
3206+
// Update returnCode if there is any EmitterError
31893207
var hasEmitterError = forEach(diagnostics, diagnostic => diagnostic.category === DiagnosticCategory.Error);
31903208

3191-
if (resolver.hasSemanticErrors() && !compilerOptions.declaration) {
3192-
// There is an semantic errror when output javascript file
3193-
// Output JS file with semantic error
3194-
returnCode = EmitReturnStatus.JSGeneratedWithSemanticErrors;
3195-
}
3196-
else if (resolver.hasSemanticErrors() && compilerOptions.declaration) {
3197-
// There is an semantic errror when output javascript and declaration file
3198-
// Output JS file with semantic error, not output declaration file
3199-
returnCode = EmitReturnStatus.DeclarationGenerationSkipped;
3200-
}
3201-
else if (hasEmitterError) {
3209+
if (hasEmitterError) {
32023210
returnCode = EmitReturnStatus.EmitErrorsEncountered;
32033211
}
32043212

src/compiler/types.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ module ts {
612612
getSymbolCount(): number;
613613
getTypeCount(): number;
614614
checkProgram(): void;
615-
emitFiles(): EmitResult;
615+
emitFiles(targetSourceFile?: SourceFile): EmitResult;
616616
getParentOfSymbol(symbol: Symbol): Symbol;
617617
getTypeOfSymbol(symbol: Symbol): Type;
618618
getPropertiesOfType(type: Type): Symbol[];
@@ -671,7 +671,6 @@ module ts {
671671
getNodeCheckFlags(node: Node): NodeCheckFlags;
672672
getEnumMemberValue(node: EnumMember): number;
673673
hasSemanticErrors(): boolean;
674-
shouldEmitDeclarations(): boolean;
675674
isDeclarationVisible(node: Declaration): boolean;
676675
isImplementationOfOverload(node: FunctionDeclaration): boolean;
677676
writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: TextWriter): void;

0 commit comments

Comments
 (0)