From 0ca03048cff58fd8dac52006ad830e1c89323830 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 3 Feb 2015 12:46:01 -0800 Subject: [PATCH 1/2] Move the code to actually emit higher up in the function. Now it it precedes all the other function declarations, and is much easier to debug. --- src/compiler/emitter.ts | 117 ++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index b15a493de9..8b4e5c3521 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -358,6 +358,65 @@ module ts { var aliasDeclarationEmitInfo: AliasDeclarationEmitInfo[] = []; + // Contains the reference paths that needs to go in the declaration file. + // Collecting this separately because reference paths need to be first thing in the declaration file + // and we could be collecting these paths from multiple files into single one with --out option + var referencePathsOutput = ""; + + if (root) { + // Emitting just a single file, so emit references in this file only + if (!compilerOptions.noResolve) { + var addedGlobalFileReference = false; + forEach(root.referencedFiles, fileReference => { + var referencedFile = tryResolveScriptReference(host, root, fileReference); + + // All the references that are not going to be part of same file + if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference + shouldEmitToOwnFile(referencedFile, compilerOptions) || // This is referenced file is emitting its own js file + !addedGlobalFileReference)) { // Or the global out file corresponding to this reference was not added + + writeReferencePath(referencedFile); + if (!isExternalModuleOrDeclarationFile(referencedFile)) { + addedGlobalFileReference = true; + } + } + }); + } + + emitNode(root); + } + else { + // Emit references corresponding to this file + var emittedReferencedFiles: SourceFile[] = []; + forEach(host.getSourceFiles(), sourceFile => { + if (!isExternalModuleOrDeclarationFile(sourceFile)) { + // Check what references need to be added + if (!compilerOptions.noResolve) { + forEach(sourceFile.referencedFiles, fileReference => { + var referencedFile = tryResolveScriptReference(host, sourceFile, fileReference); + + // If the reference file is a declaration file or an external module, emit that reference + if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) && + !contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted + + writeReferencePath(referencedFile); + emittedReferencedFiles.push(referencedFile); + } + }); + } + + emitNode(sourceFile); + } + }); + } + + return { + reportedDeclarationError, + aliasDeclarationEmitInfo, + synchronousDeclarationOutput: writer.getText(), + referencePathsOutput, + } + function createAndSetNewTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter { var writer = createTextWriter(newLine); writer.trackSymbol = trackSymbol; @@ -1402,10 +1461,6 @@ module ts { } } - // Contains the reference paths that needs to go in the declaration file. - // Collecting this separately because reference paths need to be first thing in the declaration file - // and we could be collecting these paths from multiple files into single one with --out option - var referencePathsOutput = ""; function writeReferencePath(referencedFile: SourceFile) { var declFileName = referencedFile.flags & NodeFlags.DeclarationFile ? referencedFile.filename // Declaration file, use declaration file name @@ -1422,60 +1477,6 @@ module ts { referencePathsOutput += "/// " + newLine; } - - if (root) { - // Emitting just a single file, so emit references in this file only - if (!compilerOptions.noResolve) { - var addedGlobalFileReference = false; - forEach(root.referencedFiles, fileReference => { - var referencedFile = tryResolveScriptReference(host, root, fileReference); - - // All the references that are not going to be part of same file - if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference - shouldEmitToOwnFile(referencedFile, compilerOptions) || // This is referenced file is emitting its own js file - !addedGlobalFileReference)) { // Or the global out file corresponding to this reference was not added - - writeReferencePath(referencedFile); - if (!isExternalModuleOrDeclarationFile(referencedFile)) { - addedGlobalFileReference = true; - } - } - }); - } - - emitNode(root); - } - else { - // Emit references corresponding to this file - var emittedReferencedFiles: SourceFile[] = []; - forEach(host.getSourceFiles(), sourceFile => { - if (!isExternalModuleOrDeclarationFile(sourceFile)) { - // Check what references need to be added - if (!compilerOptions.noResolve) { - forEach(sourceFile.referencedFiles, fileReference => { - var referencedFile = tryResolveScriptReference(host, sourceFile, fileReference); - - // If the reference file is a declaration file or an external module, emit that reference - if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) && - !contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted - - writeReferencePath(referencedFile); - emittedReferencedFiles.push(referencedFile); - } - }); - } - - emitNode(sourceFile); - } - }); - } - - return { - reportedDeclarationError, - aliasDeclarationEmitInfo, - synchronousDeclarationOutput: writer.getText(), - referencePathsOutput, - } } export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] { From 838b9b699827a822dd9b3eb34cb2f596b27b5e2b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 3 Feb 2015 13:15:28 -0800 Subject: [PATCH 2/2] Provide an experimental flag that allows us to emit declarations except for nodes marked with '@internal'. --- src/compiler/commandLineParser.ts | 6 +++++ .../diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 4 +++ src/compiler/emitter.ts | 24 +++++++++++++++--- src/compiler/tsc.ts | 2 +- src/compiler/types.ts | 2 ++ src/harness/harness.ts | 5 +++- tests/baselines/reference/stripInternal1.js | 25 +++++++++++++++++++ .../baselines/reference/stripInternal1.types | 12 +++++++++ tests/cases/compiler/stripInternal1.ts | 8 ++++++ 10 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/stripInternal1.js create mode 100644 tests/baselines/reference/stripInternal1.types create mode 100644 tests/cases/compiler/stripInternal1.ts diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 23bbba5c6c..a46f916864 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -134,6 +134,12 @@ module ts { type: "boolean", description: Diagnostics.Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures, }, + { + name: "stripInternal", + type: "boolean", + description: Diagnostics.Do_not_emit_declarations_for_code_that_has_an_internal_annotation, + experimental: true + }, { name: "target", shortName: "t", diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index dc7ef322c9..4b10b50e31 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -433,6 +433,7 @@ module ts { File_0_not_found: { code: 6053, category: DiagnosticCategory.Error, key: "File '{0}' not found." }, File_0_must_have_extension_ts_or_d_ts: { code: 6054, category: DiagnosticCategory.Error, key: "File '{0}' must have extension '.ts' or '.d.ts'." }, Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." }, + Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5ee826812f..456c97a7c7 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1725,6 +1725,10 @@ "category": "Message", "code": 6055 }, + "Do not emit declarations for code that has an '@internal' annotation.": { + "category": "Message", + "code": 6056 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 8b4e5c3521..edf9d9ae4c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -355,6 +355,7 @@ module ts { var reportedDeclarationError = false; var emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments; + var emit = compilerOptions.stripInternal ? stripInternal : emitNode; var aliasDeclarationEmitInfo: AliasDeclarationEmitInfo[] = []; @@ -383,7 +384,7 @@ module ts { }); } - emitNode(root); + emitSourceFile(root); } else { // Emit references corresponding to this file @@ -405,7 +406,7 @@ module ts { }); } - emitNode(sourceFile); + emitSourceFile(sourceFile); } }); } @@ -417,6 +418,23 @@ module ts { referencePathsOutput, } + function hasInternalAnnotation(range: CommentRange) { + var text = currentSourceFile.text; + var comment = text.substring(range.pos, range.end); + return comment.indexOf("@internal") >= 0; + } + + function stripInternal(node: Node) { + if (node) { + var leadingCommentRanges = getLeadingCommentRanges(currentSourceFile.text, node.pos); + if (forEach(leadingCommentRanges, hasInternalAnnotation)) { + return; + } + + emitNode(node); + } + } + function createAndSetNewTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter { var writer = createTextWriter(newLine); writer.trackSymbol = trackSymbol; @@ -522,7 +540,7 @@ module ts { function emitLines(nodes: Node[]) { for (var i = 0, n = nodes.length; i < n; i++) { - emitNode(nodes[i]); + emit(nodes[i]); } } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 52a9fb110d..960ce70604 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -413,7 +413,7 @@ module ts { output += getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine; // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") - var optsList = optionDeclarations.slice(); + var optsList = filter(optionDeclarations.slice(), v => !v.experimental); optsList.sort((a, b) => compareValues(a.name.toLowerCase(), b.name.toLowerCase())); // We want our descriptions to align at the same column in our output, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c8572c6b5c..3675310895 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1476,6 +1476,7 @@ module ts { target?: ScriptTarget; version?: boolean; watch?: boolean; + stripInternal?: boolean; [option: string]: string | number | boolean; } @@ -1514,6 +1515,7 @@ module ts { description?: DiagnosticMessage; // The message describing what the command line switch does paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter error?: DiagnosticMessage; // The error given when the argument does not fit a customized 'type' + experimental?: boolean; } export const enum CharacterCodes { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 85bd02c117..86f0ad1433 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1015,6 +1015,9 @@ module Harness { options.removeComments = setting.value === 'false'; break; + case 'stripinternal': + options.stripInternal = !!setting.value; + case 'usecasesensitivefilenames': useCaseSensitiveFileNames = setting.value === 'true'; break; @@ -1454,7 +1457,7 @@ module Harness { var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines // List of allowed metadata names - var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noemitonerror", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "includebuiltfile", "suppressimplicitanyindexerrors"]; + var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noemitonerror", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "includebuiltfile", "suppressimplicitanyindexerrors", "stripinternal"]; function extractCompilerSettings(content: string): CompilerSetting[] { diff --git a/tests/baselines/reference/stripInternal1.js b/tests/baselines/reference/stripInternal1.js new file mode 100644 index 0000000000..9deadf1fc3 --- /dev/null +++ b/tests/baselines/reference/stripInternal1.js @@ -0,0 +1,25 @@ +//// [stripInternal1.ts] + +class C { + foo(): void { } + // @internal + bar(): void { } +} + +//// [stripInternal1.js] +var C = (function () { + function C() { + } + C.prototype.foo = function () { + }; + // @internal + C.prototype.bar = function () { + }; + return C; +})(); + + +//// [stripInternal1.d.ts] +declare class C { + foo(): void; +} diff --git a/tests/baselines/reference/stripInternal1.types b/tests/baselines/reference/stripInternal1.types new file mode 100644 index 0000000000..8452de4559 --- /dev/null +++ b/tests/baselines/reference/stripInternal1.types @@ -0,0 +1,12 @@ +=== tests/cases/compiler/stripInternal1.ts === + +class C { +>C : C + + foo(): void { } +>foo : () => void + + // @internal + bar(): void { } +>bar : () => void +} diff --git a/tests/cases/compiler/stripInternal1.ts b/tests/cases/compiler/stripInternal1.ts new file mode 100644 index 0000000000..77f65e6119 --- /dev/null +++ b/tests/cases/compiler/stripInternal1.ts @@ -0,0 +1,8 @@ +// @declaration:true +// @stripInternal:true + +class C { + foo(): void { } + // @internal + bar(): void { } +} \ No newline at end of file