Skip to content

Commit 2f624f5

Browse files
committed
Expose transformations as public API
1 parent a7728f8 commit 2f624f5

25 files changed

+459
-77
lines changed

Gulpfile.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const {runTestsInParallel} = mochaParallel;
4141
Error.stackTraceLimit = 1000;
4242

4343
const cmdLineOptions = minimist(process.argv.slice(2), {
44-
boolean: ["debug", "light", "colors", "lint", "soft"],
44+
boolean: ["debug", "inspect", "light", "colors", "lint", "soft"],
4545
string: ["browser", "tests", "host", "reporter", "stackTraceLimit"],
4646
alias: {
4747
d: "debug",
@@ -57,6 +57,7 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
5757
soft: false,
5858
colors: process.env.colors || process.env.color || true,
5959
debug: process.env.debug || process.env.d,
60+
inspect: process.env.inspect,
6061
host: process.env.TYPESCRIPT_HOST || process.env.host || "node",
6162
browser: process.env.browser || process.env.b || "IE",
6263
tests: process.env.test || process.env.tests || process.env.t,
@@ -588,6 +589,7 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
588589
cleanTestDirs((err) => {
589590
if (err) { console.error(err); failWithStatus(err, 1); }
590591
const debug = cmdLineOptions["debug"];
592+
const inspect = cmdLineOptions["inspect"];
591593
const tests = cmdLineOptions["tests"];
592594
const light = cmdLineOptions["light"];
593595
const stackTraceLimit = cmdLineOptions["stackTraceLimit"];
@@ -624,7 +626,10 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
624626
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
625627
if (!runInParallel) {
626628
const args = [];
627-
if (debug) {
629+
if (inspect) {
630+
args.push("--inspect");
631+
}
632+
if (inspect || debug) {
628633
args.push("--debug-brk");
629634
}
630635
args.push("-R", reporter);

Jakefile.js

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ var servicesSources = [
150150
"shims.ts",
151151
"signatureHelp.ts",
152152
"symbolDisplay.ts",
153+
"transform.ts",
153154
"transpile.ts",
154155
// Formatting
155156
"formatting/formatting.ts",
@@ -270,6 +271,8 @@ var harnessSources = harnessCoreSources.concat([
270271
"matchFiles.ts",
271272
"initializeTSConfig.ts",
272273
"printer.ts",
274+
"transform.ts",
275+
"customTransforms.ts",
273276
].map(function (f) {
274277
return path.join(unittestsDirectory, f);
275278
})).concat([
@@ -919,6 +922,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
919922
}
920923

921924
var debug = process.env.debug || process.env.d;
925+
var inspect = process.env.inspect;
922926
tests = process.env.test || process.env.tests || process.env.t;
923927
var light = process.env.light || false;
924928
var stackTraceLimit = process.env.stackTraceLimit;
@@ -948,18 +952,39 @@ function runConsoleTests(defaultReporter, runInParallel) {
948952
testTimeout = 800000;
949953
}
950954

951-
colors = process.env.colors || process.env.color;
952-
colors = colors ? ' --no-colors ' : ' --colors ';
953-
reporter = process.env.reporter || process.env.r || defaultReporter;
954-
var bail = (process.env.bail || process.env.b) ? "--bail" : "";
955+
var colors = process.env.colors || process.env.color || true;
956+
var reporter = process.env.reporter || process.env.r || defaultReporter;
957+
var bail = process.env.bail || process.env.b;
955958
var lintFlag = process.env.lint !== 'false';
956959

957960
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
958961
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
959962
if (!runInParallel) {
960963
var startTime = mark();
961-
tests = tests ? ' -g "' + tests + '"' : '';
962-
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + bail + ' -t ' + testTimeout + ' ' + run;
964+
var args = [];
965+
if (inspect) {
966+
args.push("--inspect");
967+
}
968+
if (inspect || debug) {
969+
args.push("--debug-brk");
970+
}
971+
args.push("-R", reporter);
972+
if (tests) {
973+
args.push("-g", `"${tests}"`);
974+
}
975+
if (colors) {
976+
args.push("--colors");
977+
}
978+
else {
979+
args.push("--no-colors");
980+
}
981+
if (bail) {
982+
args.push("--bail");
983+
}
984+
args.push("-t", testTimeout);
985+
args.push(run);
986+
987+
var cmd = "mocha " + args.join(" ");
963988
console.log(cmd);
964989

965990
var savedNodeEnv = process.env.NODE_ENV;
@@ -980,7 +1005,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
9801005
var savedNodeEnv = process.env.NODE_ENV;
9811006
process.env.NODE_ENV = "development";
9821007
var startTime = mark();
983-
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
1008+
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: !colors }, function (err) {
9841009
process.env.NODE_ENV = savedNodeEnv;
9851010
measure(startTime);
9861011
// last worker clean everything and runs linter in case if there were no errors

src/compiler/comments.ts

Lines changed: 86 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,14 @@ namespace ts {
4141
}
4242

4343
if (node) {
44-
const { pos, end } = getCommentRange(node);
45-
const emitFlags = getEmitFlags(node);
44+
hasWrittenComment = false;
45+
46+
const emitNode = node.emitNode;
47+
const emitFlags = emitNode && emitNode.flags;
48+
const { pos, end } = emitNode && emitNode.commentRange || node;
4649
if ((pos < 0 && end < 0) || (pos === end)) {
4750
// Both pos and end are synthesized, so just emit the node without comments.
48-
if (emitFlags & EmitFlags.NoNestedComments) {
49-
disabled = true;
50-
emitCallback(hint, node);
51-
disabled = false;
52-
}
53-
else {
54-
emitCallback(hint, node);
55-
}
51+
emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback);
5652
}
5753
else {
5854
if (extendedDiagnostics) {
@@ -92,17 +88,10 @@ namespace ts {
9288
performance.measure("commentTime", "preEmitNodeWithComment");
9389
}
9490

95-
if (emitFlags & EmitFlags.NoNestedComments) {
96-
disabled = true;
97-
emitCallback(hint, node);
98-
disabled = false;
99-
}
100-
else {
101-
emitCallback(hint, node);
102-
}
91+
emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback);
10392

10493
if (extendedDiagnostics) {
105-
performance.mark("beginEmitNodeWithComment");
94+
performance.mark("postEmitNodeWithComment");
10695
}
10796

10897
// Restore previous container state.
@@ -117,12 +106,89 @@ namespace ts {
117106
}
118107

119108
if (extendedDiagnostics) {
120-
performance.measure("commentTime", "beginEmitNodeWithComment");
109+
performance.measure("commentTime", "postEmitNodeWithComment");
121110
}
122111
}
123112
}
124113
}
125114

115+
function emitNodeWithSynthesizedComments(hint: EmitHint, node: Node, emitNode: EmitNode, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
116+
const leadingComments = emitNode && emitNode.leadingComments;
117+
if (some(leadingComments)) {
118+
if (extendedDiagnostics) {
119+
performance.mark("preEmitNodeWithSynthesizedComments");
120+
}
121+
122+
forEach(leadingComments, emitLeadingSynthesizedComment);
123+
124+
if (extendedDiagnostics) {
125+
performance.measure("commentTime", "preEmitNodeWithSynthesizedComments");
126+
}
127+
}
128+
129+
emitNodeWithNestedComments(hint, node, emitFlags, emitCallback);
130+
131+
const trailingComments = emitNode && emitNode.trailingComments;
132+
if (some(trailingComments)) {
133+
if (extendedDiagnostics) {
134+
performance.mark("postEmitNodeWithSynthesizedComments");
135+
}
136+
137+
debugger;
138+
forEach(trailingComments, emitTrailingSynthesizedComment);
139+
140+
if (extendedDiagnostics) {
141+
performance.measure("commentTime", "postEmitNodeWithSynthesizedComments");
142+
}
143+
}
144+
}
145+
146+
function emitLeadingSynthesizedComment(comment: SynthesizedComment) {
147+
if (comment.kind === SyntaxKind.SingleLineCommentTrivia) {
148+
writer.writeLine();
149+
}
150+
writeSynthesizedComment(comment);
151+
if (comment.hasTrailingNewLine || comment.kind === SyntaxKind.SingleLineCommentTrivia) {
152+
writer.writeLine();
153+
}
154+
else {
155+
writer.write(" ");
156+
}
157+
}
158+
159+
function emitTrailingSynthesizedComment(comment: SynthesizedComment) {
160+
if (!writer.isAtStartOfLine()) {
161+
writer.write(" ");
162+
}
163+
writeSynthesizedComment(comment);
164+
if (comment.hasTrailingNewLine) {
165+
writer.writeLine();
166+
}
167+
}
168+
169+
function writeSynthesizedComment(comment: SynthesizedComment) {
170+
const text = formatSynthesizedComment(comment);
171+
const lineMap = comment.kind === SyntaxKind.MultiLineCommentTrivia ? computeLineStarts(text) : undefined;
172+
writeCommentRange(text, lineMap, writer, 0, text.length, newLine);
173+
}
174+
175+
function formatSynthesizedComment(comment: SynthesizedComment) {
176+
return comment.kind === SyntaxKind.MultiLineCommentTrivia
177+
? `/*${comment.text}*/`
178+
: `//${comment.text}`;
179+
}
180+
181+
function emitNodeWithNestedComments(hint: EmitHint, node: Node, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
182+
if (emitFlags & EmitFlags.NoNestedComments) {
183+
disabled = true;
184+
emitCallback(hint, node);
185+
disabled = false;
186+
}
187+
else {
188+
emitCallback(hint, node);
189+
}
190+
}
191+
126192
function emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) {
127193
if (extendedDiagnostics) {
128194
performance.mark("preEmitBodyWithDetachedComments");

src/compiler/emitter.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@ namespace ts {
1010

1111
/*@internal*/
1212
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
13-
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult {
13+
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: Transformer[]): EmitResult {
1414
const compilerOptions = host.getCompilerOptions();
1515
const moduleKind = getEmitModuleKind(compilerOptions);
1616
const sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined;
1717
const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined;
1818
const emitterDiagnostics = createDiagnosticCollection();
1919
const newLine = host.getNewLine();
20-
const transformers = emitOnlyDtsFiles ? [] : getTransformers(compilerOptions);
2120
const writer = createTextWriter(newLine);
2221
const sourceMap = createSourceMapWriter(host, writer);
2322

@@ -56,9 +55,7 @@ namespace ts {
5655
performance.measure("printTime", "beforePrint");
5756

5857
// Clean up emit nodes on parse tree
59-
for (const sourceFile of sourceFiles) {
60-
disposeEmitNodes(sourceFile);
61-
}
58+
transform.dispose();
6259

6360
return {
6461
emitSkipped,
@@ -756,9 +753,6 @@ namespace ts {
756753
// SyntaxKind.NumericLiteral
757754
function emitNumericLiteral(node: NumericLiteral) {
758755
emitLiteral(node);
759-
if (node.trailingComment) {
760-
write(` /*${node.trailingComment}*/`);
761-
}
762756
}
763757

764758
// SyntaxKind.StringLiteral

src/compiler/factory.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,6 +1906,34 @@ namespace ts {
19061906
return node;
19071907
}
19081908

1909+
export function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined {
1910+
const emitNode = node.emitNode;
1911+
return emitNode && emitNode.leadingComments;
1912+
}
1913+
1914+
export function setSyntheticLeadingComments<T extends Node>(node: T, comments: SynthesizedComment[]) {
1915+
getOrCreateEmitNode(node).leadingComments = comments;
1916+
return node;
1917+
}
1918+
1919+
export function addSyntheticLeadingComment<T extends Node>(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) {
1920+
return setSyntheticLeadingComments(node, append(getSyntheticLeadingComments(node), <SynthesizedComment>{ kind, pos: -1, end: -1, hasTrailingNewLine, text }));
1921+
}
1922+
1923+
export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined {
1924+
const emitNode = node.emitNode;
1925+
return emitNode && emitNode.trailingComments;
1926+
}
1927+
1928+
export function setSyntheticTrailingComments<T extends Node>(node: T, comments: SynthesizedComment[]) {
1929+
getOrCreateEmitNode(node).trailingComments = comments;
1930+
return node;
1931+
}
1932+
1933+
export function addSyntheticTrailingComment<T extends Node>(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) {
1934+
return setSyntheticTrailingComments(node, append(getSyntheticTrailingComments(node), <SynthesizedComment>{ kind, pos: -1, end: -1, hasTrailingNewLine, text }));
1935+
}
1936+
19091937
/**
19101938
* Gets the constant value to emit for an expression.
19111939
*/
@@ -2018,13 +2046,17 @@ namespace ts {
20182046
function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode) {
20192047
const {
20202048
flags,
2049+
leadingComments,
2050+
trailingComments,
20212051
commentRange,
20222052
sourceMapRange,
20232053
tokenSourceMapRanges,
20242054
constantValue,
20252055
helpers
20262056
} = sourceEmitNode;
20272057
if (!destEmitNode) destEmitNode = {};
2058+
if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments);
2059+
if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments);
20282060
if (flags) destEmitNode.flags = flags;
20292061
if (commentRange) destEmitNode.commentRange = commentRange;
20302062
if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange;

src/compiler/parser.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5816,7 +5816,11 @@ namespace ts {
58165816
}
58175817
}
58185818

5819-
const range = { pos: triviaScanner.getTokenPos(), end: triviaScanner.getTextPos(), kind: triviaScanner.getToken() };
5819+
const range = {
5820+
kind: <SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia>triviaScanner.getToken(),
5821+
pos: triviaScanner.getTokenPos(),
5822+
end: triviaScanner.getTextPos(),
5823+
};
58205824

58215825
const comment = sourceText.substring(range.pos, range.end);
58225826
const referencePathMatchResult = getFileReferenceFromReferencePath(comment, range);

src/compiler/program.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -754,15 +754,15 @@ namespace ts {
754754
return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false));
755755
}
756756

757-
function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean): EmitResult {
758-
return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles));
757+
function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers): EmitResult {
758+
return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers));
759759
}
760760

761761
function isEmitBlocked(emitFileName: string): boolean {
762762
return hasEmitBlockingDiagnostics.contains(toPath(emitFileName, currentDirectory, getCanonicalFileName));
763763
}
764764

765-
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean): EmitResult {
765+
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
766766
let declarationDiagnostics: Diagnostic[] = [];
767767

768768
if (options.noEmit) {
@@ -804,11 +804,13 @@ namespace ts {
804804

805805
performance.mark("beforeEmit");
806806

807+
const transformers = emitOnlyDtsFiles ? [] : getTransformers(options, customTransformers);
807808
const emitResult = emitFiles(
808809
emitResolver,
809810
getEmitHost(writeFileCallback),
810811
sourceFile,
811-
emitOnlyDtsFiles);
812+
emitOnlyDtsFiles,
813+
transformers);
812814

813815
performance.mark("afterEmit");
814816
performance.measure("Emit", "beforeEmit", "afterEmit");

0 commit comments

Comments
 (0)