Skip to content

Commit 031a637

Browse files
committed
Switch back to have tsc.ts the only file thats different in tsc.js generation now that api has tests
1 parent 46e3d1c commit 031a637

4 files changed

Lines changed: 392 additions & 394 deletions

File tree

src/compiler/tsc.ts

Lines changed: 391 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,394 @@
1-
/// <reference path="tscLib.ts"/>
1+
/// <reference path="program.ts"/>
2+
/// <reference path="watchedProgram.ts"/>
3+
/// <reference path="commandLineParser.ts"/>
4+
5+
namespace ts {
6+
interface Statistic {
7+
name: string;
8+
value: string;
9+
}
10+
11+
function countLines(program: Program): number {
12+
let count = 0;
13+
forEach(program.getSourceFiles(), file => {
14+
count += getLineStarts(file).length;
15+
});
16+
return count;
17+
}
18+
19+
function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string {
20+
const diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
21+
return <string>diagnostic.messageText;
22+
}
23+
24+
let reportDiagnostic = createDiagnosticReporter(sys, reportDiagnosticSimply);
25+
function udpateReportDiagnostic(options: CompilerOptions) {
26+
if (options.pretty) {
27+
reportDiagnostic = createDiagnosticReporter(sys, reportDiagnosticWithColorAndContext);
28+
}
29+
}
30+
31+
function padLeft(s: string, length: number) {
32+
while (s.length < length) {
33+
s = " " + s;
34+
}
35+
return s;
36+
}
37+
38+
function padRight(s: string, length: number) {
39+
while (s.length < length) {
40+
s = s + " ";
41+
}
42+
43+
return s;
44+
}
45+
46+
function isJSONSupported() {
47+
return typeof JSON === "object" && typeof JSON.parse === "function";
48+
}
49+
50+
export function executeCommandLine(args: string[]): void {
51+
const commandLine = parseCommandLine(args);
52+
53+
// Configuration file name (if any)
54+
let configFileName: string;
55+
if (commandLine.options.locale) {
56+
if (!isJSONSupported()) {
57+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"));
58+
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
59+
}
60+
validateLocaleAndSetLanguage(commandLine.options.locale, sys, commandLine.errors);
61+
}
62+
63+
// If there are any errors due to command line parsing and/or
64+
// setting up localization, report them and quit.
65+
if (commandLine.errors.length > 0) {
66+
reportDiagnostics(commandLine.errors, reportDiagnostic);
67+
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
68+
}
69+
70+
if (commandLine.options.init) {
71+
writeConfigFile(commandLine.options, commandLine.fileNames);
72+
return sys.exit(ExitStatus.Success);
73+
}
74+
75+
if (commandLine.options.version) {
76+
printVersion();
77+
return sys.exit(ExitStatus.Success);
78+
}
79+
80+
if (commandLine.options.help || commandLine.options.all) {
81+
printVersion();
82+
printHelp(commandLine.options.all);
83+
return sys.exit(ExitStatus.Success);
84+
}
85+
86+
if (commandLine.options.project) {
87+
if (!isJSONSupported()) {
88+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"));
89+
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
90+
}
91+
if (commandLine.fileNames.length !== 0) {
92+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
93+
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
94+
}
95+
96+
const fileOrDirectory = normalizePath(commandLine.options.project);
97+
if (!fileOrDirectory /* current directory "." */ || sys.directoryExists(fileOrDirectory)) {
98+
configFileName = combinePaths(fileOrDirectory, "tsconfig.json");
99+
if (!sys.fileExists(configFileName)) {
100+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project));
101+
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
102+
}
103+
}
104+
else {
105+
configFileName = fileOrDirectory;
106+
if (!sys.fileExists(configFileName)) {
107+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project));
108+
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
109+
}
110+
}
111+
}
112+
else if (commandLine.fileNames.length === 0 && isJSONSupported()) {
113+
const searchPath = normalizePath(sys.getCurrentDirectory());
114+
configFileName = findConfigFile(searchPath, sys.fileExists);
115+
}
116+
117+
if (commandLine.fileNames.length === 0 && !configFileName) {
118+
printVersion();
119+
printHelp(commandLine.options.all);
120+
return sys.exit(ExitStatus.Success);
121+
}
122+
123+
const commandLineOptions = commandLine.options;
124+
if (configFileName) {
125+
const reportWatchDiagnostic = createWatchDiagnosticReporter();
126+
const configParseResult = parseConfigFile(configFileName, commandLineOptions, sys, reportDiagnostic, reportWatchDiagnostic);
127+
udpateReportDiagnostic(configParseResult.options);
128+
if (isWatchSet(configParseResult.options)) {
129+
reportWatchModeWithoutSysSupport();
130+
createWatchModeWithConfigFile(configParseResult, commandLineOptions, createWatchingSystemHost(reportWatchDiagnostic));
131+
}
132+
else {
133+
performCompilation(configParseResult.fileNames, configParseResult.options);
134+
}
135+
}
136+
else {
137+
udpateReportDiagnostic(commandLineOptions);
138+
if (isWatchSet(commandLineOptions)) {
139+
reportWatchModeWithoutSysSupport();
140+
createWatchModeWithoutConfigFile(commandLine.fileNames, commandLineOptions, createWatchingSystemHost());
141+
}
142+
else {
143+
performCompilation(commandLine.fileNames, commandLineOptions);
144+
}
145+
}
146+
}
147+
148+
function reportWatchModeWithoutSysSupport() {
149+
if (!sys.watchFile || !sys.watchDirectory) {
150+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));
151+
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
152+
}
153+
}
154+
155+
function performCompilation(rootFileNames: string[], compilerOptions: CompilerOptions) {
156+
const compilerHost = createCompilerHost(compilerOptions);
157+
enableStatistics(compilerOptions);
158+
159+
const program = createProgram(rootFileNames, compilerOptions, compilerHost);
160+
const exitStatus = compileProgram(sys, program, () => program.emit(), reportDiagnostic);
161+
162+
reportStatistics(program);
163+
return sys.exit(exitStatus);
164+
}
165+
166+
function createWatchingSystemHost(reportWatchDiagnostic?: DiagnosticReporter) {
167+
const watchingHost = ts.createWatchingSystemHost(/*pretty*/ undefined, sys, parseConfigFile, reportDiagnostic, reportWatchDiagnostic);
168+
watchingHost.beforeCompile = enableStatistics;
169+
const afterCompile = watchingHost.afterCompile;
170+
watchingHost.afterCompile = (host, program, builder) => {
171+
afterCompile(host, program, builder);
172+
reportStatistics(program);
173+
};
174+
return watchingHost;
175+
}
176+
177+
function enableStatistics(compilerOptions: CompilerOptions) {
178+
if (compilerOptions.diagnostics || compilerOptions.extendedDiagnostics) {
179+
performance.enable();
180+
}
181+
}
182+
183+
function reportStatistics(program: Program) {
184+
let statistics: Statistic[];
185+
const compilerOptions = program.getCompilerOptions();
186+
if (compilerOptions.diagnostics || compilerOptions.extendedDiagnostics) {
187+
statistics = [];
188+
const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
189+
reportCountStatistic("Files", program.getSourceFiles().length);
190+
reportCountStatistic("Lines", countLines(program));
191+
reportCountStatistic("Nodes", program.getNodeCount());
192+
reportCountStatistic("Identifiers", program.getIdentifierCount());
193+
reportCountStatistic("Symbols", program.getSymbolCount());
194+
reportCountStatistic("Types", program.getTypeCount());
195+
196+
if (memoryUsed >= 0) {
197+
reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K");
198+
}
199+
200+
const programTime = performance.getDuration("Program");
201+
const bindTime = performance.getDuration("Bind");
202+
const checkTime = performance.getDuration("Check");
203+
const emitTime = performance.getDuration("Emit");
204+
if (compilerOptions.extendedDiagnostics) {
205+
performance.forEachMeasure((name, duration) => reportTimeStatistic(`${name} time`, duration));
206+
}
207+
else {
208+
// Individual component times.
209+
// Note: To match the behavior of previous versions of the compiler, the reported parse time includes
210+
// I/O read time and processing time for triple-slash references and module imports, and the reported
211+
// emit time includes I/O write time. We preserve this behavior so we can accurately compare times.
212+
reportTimeStatistic("I/O read", performance.getDuration("I/O Read"));
213+
reportTimeStatistic("I/O write", performance.getDuration("I/O Write"));
214+
reportTimeStatistic("Parse time", programTime);
215+
reportTimeStatistic("Bind time", bindTime);
216+
reportTimeStatistic("Check time", checkTime);
217+
reportTimeStatistic("Emit time", emitTime);
218+
}
219+
reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime);
220+
reportStatistics();
221+
222+
performance.disable();
223+
}
224+
225+
function reportStatistics() {
226+
let nameSize = 0;
227+
let valueSize = 0;
228+
for (const { name, value } of statistics) {
229+
if (name.length > nameSize) {
230+
nameSize = name.length;
231+
}
232+
233+
if (value.length > valueSize) {
234+
valueSize = value.length;
235+
}
236+
}
237+
238+
for (const { name, value } of statistics) {
239+
sys.write(padRight(name + ":", nameSize + 2) + padLeft(value.toString(), valueSize) + sys.newLine);
240+
}
241+
}
242+
243+
function reportStatisticalValue(name: string, value: string) {
244+
statistics.push({ name, value });
245+
}
246+
247+
function reportCountStatistic(name: string, count: number) {
248+
reportStatisticalValue(name, "" + count);
249+
}
250+
251+
function reportTimeStatistic(name: string, time: number) {
252+
reportStatisticalValue(name, (time / 1000).toFixed(2) + "s");
253+
}
254+
}
255+
256+
function printVersion() {
257+
sys.write(getDiagnosticText(Diagnostics.Version_0, ts.version) + sys.newLine);
258+
}
259+
260+
function printHelp(showAllOptions: boolean) {
261+
const output: string[] = [];
262+
263+
// We want to align our "syntax" and "examples" commands to a certain margin.
264+
const syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
265+
const examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
266+
let marginLength = Math.max(syntaxLength, examplesLength);
267+
268+
// Build up the syntactic skeleton.
269+
let syntax = makePadding(marginLength - syntaxLength);
270+
syntax += "tsc [" + getDiagnosticText(Diagnostics.options) + "] [" + getDiagnosticText(Diagnostics.file) + " ...]";
271+
272+
output.push(getDiagnosticText(Diagnostics.Syntax_Colon_0, syntax));
273+
output.push(sys.newLine + sys.newLine);
274+
275+
// Build up the list of examples.
276+
const padding = makePadding(marginLength);
277+
output.push(getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine);
278+
output.push(padding + "tsc --outFile file.js file.ts" + sys.newLine);
279+
output.push(padding + "tsc @args.txt" + sys.newLine);
280+
output.push(sys.newLine);
281+
282+
output.push(getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine);
283+
284+
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
285+
const optsList = showAllOptions ?
286+
optionDeclarations.slice().sort((a, b) => compareValues<string>(a.name.toLowerCase(), b.name.toLowerCase())) :
287+
filter(optionDeclarations.slice(), v => v.showInSimplifiedHelpView);
288+
289+
// We want our descriptions to align at the same column in our output,
290+
// so we keep track of the longest option usage string.
291+
marginLength = 0;
292+
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
293+
const descriptionColumn: string[] = [];
294+
295+
const optionsDescriptionMap = createMap<string[]>(); // Map between option.description and list of option.type if it is a kind
296+
297+
for (let i = 0; i < optsList.length; i++) {
298+
const option = optsList[i];
299+
300+
// If an option lacks a description,
301+
// it is not officially supported.
302+
if (!option.description) {
303+
continue;
304+
}
305+
306+
let usageText = " ";
307+
if (option.shortName) {
308+
usageText += "-" + option.shortName;
309+
usageText += getParamType(option);
310+
usageText += ", ";
311+
}
312+
313+
usageText += "--" + option.name;
314+
usageText += getParamType(option);
315+
316+
usageColumn.push(usageText);
317+
let description: string;
318+
319+
if (option.name === "lib") {
320+
description = getDiagnosticText(option.description);
321+
const element = (<CommandLineOptionOfListType>option).element;
322+
const typeMap = <Map<number | string>>element.type;
323+
optionsDescriptionMap.set(description, arrayFrom(typeMap.keys()).map(key => `'${key}'`));
324+
}
325+
else {
326+
description = getDiagnosticText(option.description);
327+
}
328+
329+
descriptionColumn.push(description);
330+
331+
// Set the new margin for the description column if necessary.
332+
marginLength = Math.max(usageText.length, marginLength);
333+
}
334+
335+
// Special case that can't fit in the loop.
336+
const usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
337+
usageColumn.push(usageText);
338+
descriptionColumn.push(getDiagnosticText(Diagnostics.Insert_command_line_options_and_files_from_a_file));
339+
marginLength = Math.max(usageText.length, marginLength);
340+
341+
// Print out each row, aligning all the descriptions on the same column.
342+
for (let i = 0; i < usageColumn.length; i++) {
343+
const usage = usageColumn[i];
344+
const description = descriptionColumn[i];
345+
const kindsList = optionsDescriptionMap.get(description);
346+
output.push(usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine);
347+
348+
if (kindsList) {
349+
output.push(makePadding(marginLength + 4));
350+
for (const kind of kindsList) {
351+
output.push(kind + " ");
352+
}
353+
output.push(sys.newLine);
354+
}
355+
}
356+
357+
for (const line of output) {
358+
sys.write(line);
359+
}
360+
return;
361+
362+
function getParamType(option: CommandLineOption) {
363+
if (option.paramType !== undefined) {
364+
return " " + getDiagnosticText(option.paramType);
365+
}
366+
return "";
367+
}
368+
369+
function makePadding(paddingLength: number): string {
370+
return Array(paddingLength + 1).join(" ");
371+
}
372+
}
373+
374+
function writeConfigFile(options: CompilerOptions, fileNames: string[]) {
375+
const currentDirectory = sys.getCurrentDirectory();
376+
const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
377+
if (sys.fileExists(file)) {
378+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file));
379+
}
380+
else {
381+
sys.writeFile(file, generateTSConfig(options, fileNames, sys.newLine));
382+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file));
383+
}
384+
385+
return;
386+
}
387+
}
388+
389+
if (ts.Debug.isDebugging) {
390+
ts.Debug.enableDebugInfo();
391+
}
2392

3393
if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
4394
ts.sys.tryEnableSourceMapsForHost();

0 commit comments

Comments
 (0)