Skip to content

Commit fab351e

Browse files
Merge pull request #1913 from Microsoft/internalDTS
Provide an experimental flag that allows us to emit declarations except for nodes marked with '@internal'.
2 parents 626277c + 838b9b6 commit fab351e

File tree

10 files changed

+141
-61
lines changed

10 files changed

+141
-61
lines changed

src/compiler/commandLineParser.ts

+6
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ module ts {
134134
type: "boolean",
135135
description: Diagnostics.Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures,
136136
},
137+
{
138+
name: "stripInternal",
139+
type: "boolean",
140+
description: Diagnostics.Do_not_emit_declarations_for_code_that_has_an_internal_annotation,
141+
experimental: true
142+
},
137143
{
138144
name: "target",
139145
shortName: "t",

src/compiler/diagnosticInformationMap.generated.ts

+1
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ module ts {
433433
File_0_not_found: { code: 6053, category: DiagnosticCategory.Error, key: "File '{0}' not found." },
434434
File_0_must_have_extension_ts_or_d_ts: { code: 6054, category: DiagnosticCategory.Error, key: "File '{0}' must have extension '.ts' or '.d.ts'." },
435435
Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." },
436+
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." },
436437
Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
437438
Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
438439
Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,10 @@
17251725
"category": "Message",
17261726
"code": 6055
17271727
},
1728+
"Do not emit declarations for code that has an '@internal' annotation.": {
1729+
"category": "Message",
1730+
"code": 6056
1731+
},
17281732

17291733
"Variable '{0}' implicitly has an '{1}' type.": {
17301734
"category": "Error",

src/compiler/emitter.ts

+78-59
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,86 @@ module ts {
355355
var reportedDeclarationError = false;
356356

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

359360
var aliasDeclarationEmitInfo: AliasDeclarationEmitInfo[] = [];
360361

362+
// Contains the reference paths that needs to go in the declaration file.
363+
// Collecting this separately because reference paths need to be first thing in the declaration file
364+
// and we could be collecting these paths from multiple files into single one with --out option
365+
var referencePathsOutput = "";
366+
367+
if (root) {
368+
// Emitting just a single file, so emit references in this file only
369+
if (!compilerOptions.noResolve) {
370+
var addedGlobalFileReference = false;
371+
forEach(root.referencedFiles, fileReference => {
372+
var referencedFile = tryResolveScriptReference(host, root, fileReference);
373+
374+
// All the references that are not going to be part of same file
375+
if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
376+
shouldEmitToOwnFile(referencedFile, compilerOptions) || // This is referenced file is emitting its own js file
377+
!addedGlobalFileReference)) { // Or the global out file corresponding to this reference was not added
378+
379+
writeReferencePath(referencedFile);
380+
if (!isExternalModuleOrDeclarationFile(referencedFile)) {
381+
addedGlobalFileReference = true;
382+
}
383+
}
384+
});
385+
}
386+
387+
emitSourceFile(root);
388+
}
389+
else {
390+
// Emit references corresponding to this file
391+
var emittedReferencedFiles: SourceFile[] = [];
392+
forEach(host.getSourceFiles(), sourceFile => {
393+
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
394+
// Check what references need to be added
395+
if (!compilerOptions.noResolve) {
396+
forEach(sourceFile.referencedFiles, fileReference => {
397+
var referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
398+
399+
// If the reference file is a declaration file or an external module, emit that reference
400+
if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) &&
401+
!contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted
402+
403+
writeReferencePath(referencedFile);
404+
emittedReferencedFiles.push(referencedFile);
405+
}
406+
});
407+
}
408+
409+
emitSourceFile(sourceFile);
410+
}
411+
});
412+
}
413+
414+
return {
415+
reportedDeclarationError,
416+
aliasDeclarationEmitInfo,
417+
synchronousDeclarationOutput: writer.getText(),
418+
referencePathsOutput,
419+
}
420+
421+
function hasInternalAnnotation(range: CommentRange) {
422+
var text = currentSourceFile.text;
423+
var comment = text.substring(range.pos, range.end);
424+
return comment.indexOf("@internal") >= 0;
425+
}
426+
427+
function stripInternal(node: Node) {
428+
if (node) {
429+
var leadingCommentRanges = getLeadingCommentRanges(currentSourceFile.text, node.pos);
430+
if (forEach(leadingCommentRanges, hasInternalAnnotation)) {
431+
return;
432+
}
433+
434+
emitNode(node);
435+
}
436+
}
437+
361438
function createAndSetNewTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter {
362439
var writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
363440
writer.trackSymbol = trackSymbol;
@@ -463,7 +540,7 @@ module ts {
463540

464541
function emitLines(nodes: Node[]) {
465542
for (var i = 0, n = nodes.length; i < n; i++) {
466-
emitNode(nodes[i]);
543+
emit(nodes[i]);
467544
}
468545
}
469546

@@ -1402,10 +1479,6 @@ module ts {
14021479
}
14031480
}
14041481

1405-
// Contains the reference paths that needs to go in the declaration file.
1406-
// Collecting this separately because reference paths need to be first thing in the declaration file
1407-
// and we could be collecting these paths from multiple files into single one with --out option
1408-
var referencePathsOutput = "";
14091482
function writeReferencePath(referencedFile: SourceFile) {
14101483
var declFileName = referencedFile.flags & NodeFlags.DeclarationFile
14111484
? referencedFile.filename // Declaration file, use declaration file name
@@ -1422,60 +1495,6 @@ module ts {
14221495

14231496
referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
14241497
}
1425-
1426-
if (root) {
1427-
// Emitting just a single file, so emit references in this file only
1428-
if (!compilerOptions.noResolve) {
1429-
var addedGlobalFileReference = false;
1430-
forEach(root.referencedFiles, fileReference => {
1431-
var referencedFile = tryResolveScriptReference(host, root, fileReference);
1432-
1433-
// All the references that are not going to be part of same file
1434-
if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
1435-
shouldEmitToOwnFile(referencedFile, compilerOptions) || // This is referenced file is emitting its own js file
1436-
!addedGlobalFileReference)) { // Or the global out file corresponding to this reference was not added
1437-
1438-
writeReferencePath(referencedFile);
1439-
if (!isExternalModuleOrDeclarationFile(referencedFile)) {
1440-
addedGlobalFileReference = true;
1441-
}
1442-
}
1443-
});
1444-
}
1445-
1446-
emitNode(root);
1447-
}
1448-
else {
1449-
// Emit references corresponding to this file
1450-
var emittedReferencedFiles: SourceFile[] = [];
1451-
forEach(host.getSourceFiles(), sourceFile => {
1452-
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
1453-
// Check what references need to be added
1454-
if (!compilerOptions.noResolve) {
1455-
forEach(sourceFile.referencedFiles, fileReference => {
1456-
var referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
1457-
1458-
// If the reference file is a declaration file or an external module, emit that reference
1459-
if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) &&
1460-
!contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted
1461-
1462-
writeReferencePath(referencedFile);
1463-
emittedReferencedFiles.push(referencedFile);
1464-
}
1465-
});
1466-
}
1467-
1468-
emitNode(sourceFile);
1469-
}
1470-
});
1471-
}
1472-
1473-
return {
1474-
reportedDeclarationError,
1475-
aliasDeclarationEmitInfo,
1476-
synchronousDeclarationOutput: writer.getText(),
1477-
referencePathsOutput,
1478-
}
14791498
}
14801499

14811500
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {

src/compiler/tsc.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ module ts {
413413
output += getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine;
414414

415415
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
416-
var optsList = optionDeclarations.slice();
416+
var optsList = filter(optionDeclarations.slice(), v => !v.experimental);
417417
optsList.sort((a, b) => compareValues<string>(a.name.toLowerCase(), b.name.toLowerCase()));
418418

419419
// We want our descriptions to align at the same column in our output,

src/compiler/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,7 @@ module ts {
14681468
target?: ScriptTarget;
14691469
version?: boolean;
14701470
watch?: boolean;
1471+
stripInternal?: boolean;
14711472
[option: string]: string | number | boolean;
14721473
}
14731474

@@ -1506,6 +1507,7 @@ module ts {
15061507
description?: DiagnosticMessage; // The message describing what the command line switch does
15071508
paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter
15081509
error?: DiagnosticMessage; // The error given when the argument does not fit a customized 'type'
1510+
experimental?: boolean;
15091511
}
15101512

15111513
export const enum CharacterCodes {

src/harness/harness.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,9 @@ module Harness {
10171017
options.removeComments = setting.value === 'false';
10181018
break;
10191019

1020+
case 'stripinternal':
1021+
options.stripInternal = !!setting.value;
1022+
10201023
case 'usecasesensitivefilenames':
10211024
useCaseSensitiveFileNames = setting.value === 'true';
10221025
break;
@@ -1464,7 +1467,7 @@ module Harness {
14641467
var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines
14651468

14661469
// List of allowed metadata names
1467-
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noemitonerror", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "includebuiltfile", "suppressimplicitanyindexerrors"];
1470+
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noemitonerror", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "includebuiltfile", "suppressimplicitanyindexerrors", "stripinternal"];
14681471

14691472
function extractCompilerSettings(content: string): CompilerSetting[] {
14701473

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [stripInternal1.ts]
2+
3+
class C {
4+
foo(): void { }
5+
// @internal
6+
bar(): void { }
7+
}
8+
9+
//// [stripInternal1.js]
10+
var C = (function () {
11+
function C() {
12+
}
13+
C.prototype.foo = function () {
14+
};
15+
// @internal
16+
C.prototype.bar = function () {
17+
};
18+
return C;
19+
})();
20+
21+
22+
//// [stripInternal1.d.ts]
23+
declare class C {
24+
foo(): void;
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
=== tests/cases/compiler/stripInternal1.ts ===
2+
3+
class C {
4+
>C : C
5+
6+
foo(): void { }
7+
>foo : () => void
8+
9+
// @internal
10+
bar(): void { }
11+
>bar : () => void
12+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @declaration:true
2+
// @stripInternal:true
3+
4+
class C {
5+
foo(): void { }
6+
// @internal
7+
bar(): void { }
8+
}

0 commit comments

Comments
 (0)