Skip to content

Commit

Permalink
Merge pull request #1913 from Microsoft/internalDTS
Browse files Browse the repository at this point in the history
Provide an experimental flag that allows us to emit declarations except for nodes marked with '@internal'.
  • Loading branch information
CyrusNajmabadi committed Feb 3, 2015
2 parents 626277c + 838b9b6 commit fab351e
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 61 deletions.
6 changes: 6 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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." },
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
137 changes: 78 additions & 59 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,86 @@ module ts {
var reportedDeclarationError = false;

var emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
var emit = compilerOptions.stripInternal ? stripInternal : emitNode;

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;
}
}
});
}

emitSourceFile(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);
}
});
}

emitSourceFile(sourceFile);
}
});
}

return {
reportedDeclarationError,
aliasDeclarationEmitInfo,
synchronousDeclarationOutput: writer.getText(),
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 = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
writer.trackSymbol = trackSymbol;
Expand Down Expand Up @@ -463,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]);
}
}

Expand Down Expand Up @@ -1402,10 +1479,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
Expand All @@ -1422,60 +1495,6 @@ module ts {

referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + 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[] {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/tsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>(a.name.toLowerCase(), b.name.toLowerCase()));

// We want our descriptions to align at the same column in our output,
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,7 @@ module ts {
target?: ScriptTarget;
version?: boolean;
watch?: boolean;
stripInternal?: boolean;
[option: string]: string | number | boolean;
}

Expand Down Expand Up @@ -1506,6 +1507,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 {
Expand Down
5 changes: 4 additions & 1 deletion src/harness/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,9 @@ module Harness {
options.removeComments = setting.value === 'false';
break;

case 'stripinternal':
options.stripInternal = !!setting.value;

case 'usecasesensitivefilenames':
useCaseSensitiveFileNames = setting.value === 'true';
break;
Expand Down Expand Up @@ -1464,7 +1467,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[] {

Expand Down
25 changes: 25 additions & 0 deletions tests/baselines/reference/stripInternal1.js
Original file line number Diff line number Diff line change
@@ -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;
}
12 changes: 12 additions & 0 deletions tests/baselines/reference/stripInternal1.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
=== tests/cases/compiler/stripInternal1.ts ===

class C {
>C : C

foo(): void { }
>foo : () => void

// @internal
bar(): void { }
>bar : () => void
}
8 changes: 8 additions & 0 deletions tests/cases/compiler/stripInternal1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @declaration:true
// @stripInternal:true

class C {
foo(): void { }
// @internal
bar(): void { }
}

0 comments on commit fab351e

Please sign in to comment.