Dont emit declaration file if there are errors in the source file

This commit is contained in:
Sheetal Nandi 2015-10-20 11:22:46 -07:00
parent 68040879c9
commit 3215438ddf
6 changed files with 52 additions and 10 deletions

View File

@ -729,7 +729,7 @@ namespace ts {
* List of supported extensions in order of file resolution precedence.
*/
export const supportedTypeScriptExtensions = ["ts", "tsx", "d.ts"];
export function getSupportedExtensions(options?: CompilerOptions): string[] {
return options && options.jsExtensions ? supportedTypeScriptExtensions.concat(options.jsExtensions) : supportedTypeScriptExtensions;
}

View File

@ -1607,9 +1607,7 @@ namespace ts {
/* @internal */
export function writeDeclarationFile(declarationFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) {
let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, declarationFilePath, sourceFile);
// TODO(shkamat): Should we not write any declaration file if any of them can produce error,
// or should we just not write this file like we are doing now
if (!emitDeclarationResult.reportedDeclarationError) {
if (!emitDeclarationResult.reportedDeclarationError && !host.isDeclarationEmitBlocked(declarationFilePath, sourceFile)) {
let declarationOutput = emitDeclarationResult.referencePathsOutput
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
let compilerOptions = host.getCompilerOptions();

View File

@ -7601,7 +7601,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
emitJavaScript(jsFilePath, sourceFile);
}
if (compilerOptions.declaration && !host.isEmitBlocked(declarationFilePath)) {
if (compilerOptions.declaration) {
writeDeclarationFile(declarationFilePath, sourceFile, host, resolver, diagnostics);
}
}

View File

@ -330,6 +330,7 @@ namespace ts {
let files: SourceFile[] = [];
let fileProcessingDiagnostics = createDiagnosticCollection();
let programDiagnostics = createDiagnosticCollection();
let emitBlockingDiagnostics = createDiagnosticCollection();
let hasEmitBlockingDiagnostics: Map<boolean> = {}; // Map storing if there is emit blocking diagnostics for given input
let commonSourceDirectory: string;
@ -393,6 +394,7 @@ namespace ts {
getDiagnosticsProducingTypeChecker,
getCommonSourceDirectory: () => commonSourceDirectory,
emit,
isDeclarationEmitBlocked,
getCurrentDirectory: () => host.getCurrentDirectory(),
getNodeCount: () => getDiagnosticsProducingTypeChecker().getNodeCount(),
getIdentifierCount: () => getDiagnosticsProducingTypeChecker().getIdentifierCount(),
@ -510,7 +512,7 @@ namespace ts {
return true;
}
function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost {
function getEmitHost(writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken): EmitHost {
return {
getCanonicalFileName: fileName => host.getCanonicalFileName(fileName),
getCommonSourceDirectory: program.getCommonSourceDirectory,
@ -521,7 +523,8 @@ namespace ts {
getSourceFiles: program.getSourceFiles,
writeFile: writeFileCallback || (
(fileName, data, writeByteOrderMark, onError) => host.writeFile(fileName, data, writeByteOrderMark, onError)),
isEmitBlocked: emitFileName => hasProperty(hasEmitBlockingDiagnostics, emitFileName),
isEmitBlocked,
isDeclarationEmitBlocked: (emitFileName, sourceFile) => program.isDeclarationEmitBlocked(emitFileName, sourceFile, cancellationToken),
};
}
@ -537,6 +540,42 @@ namespace ts {
return runWithCancellationToken(() => emitWorker(this, sourceFile, writeFileCallback, cancellationToken));
}
function isDeclarationEmitBlocked(emitFileName: string, sourceFile?: SourceFile, cancellationToken?: CancellationToken): boolean {
if (isEmitBlocked(emitFileName)) {
return true;
}
// Dont check for emit blocking options diagnostics because that check per emit file is already covered in isEmitBlocked
// We dont want to end up blocking declaration emit of one file because other file results in emit blocking error
if (getOptionsDiagnostics(cancellationToken, /*includeEmitBlockingDiagnostics*/false).length ||
getGlobalDiagnostics().length) {
return true;
}
if (sourceFile) {
// Do not generate declaration file for this if there are any errors in this file or any of the declaration files
return hasSyntaxOrSemanticDiagnostics(sourceFile) ||
forEach(files, sourceFile => isDeclarationFile(sourceFile) && hasSyntaxOrSemanticDiagnostics(sourceFile));
}
// Check if the bundled emit source files have errors
return forEach(files, sourceFile => {
// Check all the files that will be bundled together as well as all the included declaration files are error free
if (!isExternalModule(sourceFile)) {
return hasSyntaxOrSemanticDiagnostics(sourceFile);
}
});
function hasSyntaxOrSemanticDiagnostics(file: SourceFile) {
return !!getSyntacticDiagnostics(file, cancellationToken).length ||
!!getSemanticDiagnostics(file, cancellationToken).length;
}
}
function isEmitBlocked(emitFileName: string): boolean {
return hasProperty(hasEmitBlockingDiagnostics, emitFileName);
}
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken): EmitResult {
// If the noEmitOnError flag is set, then check if we have any errors so far. If so,
// immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
@ -559,7 +598,7 @@ namespace ts {
let emitResult = emitFiles(
emitResolver,
getEmitHost(writeFileCallback),
getEmitHost(writeFileCallback, cancellationToken),
sourceFile);
emitTime += new Date().getTime() - start;
@ -821,10 +860,13 @@ namespace ts {
});
}
function getOptionsDiagnostics(): Diagnostic[] {
function getOptionsDiagnostics(cancellationToken?: CancellationToken, includeEmitBlockingDiagnostics?: boolean): Diagnostic[] {
let allDiagnostics: Diagnostic[] = [];
addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics());
addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics());
if (!includeEmitBlockingDiagnostics) {
addRange(allDiagnostics, emitBlockingDiagnostics.getGlobalDiagnostics());
}
return sortAndDeduplicateDiagnostics(allDiagnostics);
}
@ -1291,7 +1333,7 @@ namespace ts {
function createEmitBlockingDiagnostics(emitFileName: string, message: DiagnosticMessage) {
hasEmitBlockingDiagnostics[emitFileName] = true;
programDiagnostics.add(createCompilerDiagnostic(message, emitFileName));
emitBlockingDiagnostics.add(createCompilerDiagnostic(message, emitFileName));
}
}
}

View File

@ -1358,6 +1358,7 @@ namespace ts {
getTypeChecker(): TypeChecker;
/* @internal */ getCommonSourceDirectory(): string;
/* @internal */ isDeclarationEmitBlocked(emitFileName: string, sourceFile?: SourceFile, cancellationToken?: CancellationToken): boolean;
// For testing purposes only. Should not be used by any other consumers (including the
// language service).

View File

@ -40,6 +40,7 @@ namespace ts {
getNewLine(): string;
isEmitBlocked(emitFileName: string): boolean;
isDeclarationEmitBlocked(emitFileName: string, sourceFile?: SourceFile): boolean;
writeFile: WriteFileCallback;
}