Merge pull request #27078 from Microsoft/commonCompilerOptionsWithBuild

Parse selected command line options with build and use them as base for solution building
This commit is contained in:
Sheetal Nandi
2018-09-14 10:10:06 -07:00
committed by GitHub
7 changed files with 201 additions and 113 deletions
+49 -46
View File
@@ -62,7 +62,8 @@ namespace ts {
/* @internal */
export const libMap = createMapFromEntries(libEntries);
const commonOptionsWithBuild: CommandLineOption[] = [
/* @internal */
export const commonOptionsWithBuild: CommandLineOption[] = [
{
name: "help",
shortName: "h",
@@ -83,6 +84,18 @@ namespace ts {
category: Diagnostics.Command_line_Options,
description: Diagnostics.Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen,
},
{
name: "listFiles",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Print_names_of_files_part_of_the_compilation
},
{
name: "listEmittedFiles",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Print_names_of_generated_files_part_of_the_compilation
},
{
name: "watch",
shortName: "w",
@@ -561,18 +574,6 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Include_modules_imported_with_json_extension
},
{
name: "listFiles",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Print_names_of_files_part_of_the_compilation
},
{
name: "listEmittedFiles",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Print_names_of_generated_files_part_of_the_compilation
},
{
name: "out",
@@ -903,17 +904,27 @@ namespace ts {
}
}
export function parseCommandLine(commandLine: ReadonlyArray<string>, readFile?: (path: string) => string | undefined): ParsedCommandLine {
const options: CompilerOptions = {};
/* @internal */
export interface OptionsBase {
[option: string]: CompilerOptionsValue | undefined;
}
/** Tuple with error messages for 'unknown compiler option', 'option requires type' */
type ParseCommandLineWorkerDiagnostics = [DiagnosticMessage, DiagnosticMessage];
function parseCommandLineWorker(
getOptionNameMap: () => OptionNameMap,
[unknownOptionDiagnostic, optionTypeMismatchDiagnostic]: ParseCommandLineWorkerDiagnostics,
commandLine: ReadonlyArray<string>,
readFile?: (path: string) => string | undefined) {
const options = {} as OptionsBase;
const fileNames: string[] = [];
const projectReferences: ProjectReference[] | undefined = undefined;
const errors: Diagnostic[] = [];
parseStrings(commandLine);
return {
options,
fileNames,
projectReferences,
errors
};
@@ -926,7 +937,7 @@ namespace ts {
parseResponseFile(s.slice(1));
}
else if (s.charCodeAt(0) === CharacterCodes.minus) {
const opt = getOptionFromName(s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true);
const opt = getOptionDeclarationFromName(getOptionNameMap, s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true);
if (opt) {
if (opt.isTSConfigOnly) {
errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name));
@@ -934,7 +945,7 @@ namespace ts {
else {
// Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
if (!args[i] && opt.type !== "boolean") {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name));
errors.push(createCompilerDiagnostic(optionTypeMismatchDiagnostic, opt.name));
}
switch (opt.type) {
@@ -971,7 +982,7 @@ namespace ts {
}
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, s));
errors.push(createCompilerDiagnostic(unknownOptionDiagnostic, s));
}
}
else {
@@ -1014,13 +1025,19 @@ namespace ts {
}
}
export function parseCommandLine(commandLine: ReadonlyArray<string>, readFile?: (path: string) => string | undefined): ParsedCommandLine {
return parseCommandLineWorker(getOptionNameMap, [
Diagnostics.Unknown_compiler_option_0,
Diagnostics.Compiler_option_0_expects_an_argument
], commandLine, readFile);
}
/** @internal */
export function getOptionFromName(optionName: string, allowShort?: boolean): CommandLineOption | undefined {
return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort);
}
/*@internal*/
export function getOptionDeclarationFromName(getOptionNameMap: () => OptionNameMap, optionName: string, allowShort = false): CommandLineOption | undefined {
function getOptionDeclarationFromName(getOptionNameMap: () => OptionNameMap, optionName: string, allowShort = false): CommandLineOption | undefined {
optionName = optionName.toLowerCase();
const { optionNameMap, shortOptionNames } = getOptionNameMap();
// Try to translate short option names to their full equivalents.
@@ -1044,25 +1061,11 @@ namespace ts {
export function parseBuildCommand(args: string[]): ParsedBuildCommand {
let buildOptionNameMap: OptionNameMap | undefined;
const returnBuildOptionNameMap = () => (buildOptionNameMap || (buildOptionNameMap = createOptionNameMap(buildOpts)));
const buildOptions: BuildOptions = {};
const projects: string[] = [];
let errors: Diagnostic[] | undefined;
for (const arg of args) {
if (arg.charCodeAt(0) === CharacterCodes.minus) {
const opt = getOptionDeclarationFromName(returnBuildOptionNameMap, arg.slice(arg.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true);
if (opt) {
buildOptions[opt.name as keyof BuildOptions] = true;
}
else {
(errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Unknown_build_option_0, arg));
}
}
else {
// Not a flag, parse as filename
projects.push(arg);
}
}
const { options, fileNames: projects, errors } = parseCommandLineWorker(returnBuildOptionNameMap, [
Diagnostics.Unknown_build_option_0,
Diagnostics.Build_option_0_requires_a_value_of_type_1
], args);
const buildOptions = options as BuildOptions;
if (projects.length === 0) {
// tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
@@ -1071,19 +1074,19 @@ namespace ts {
// Nonsensical combinations
if (buildOptions.clean && buildOptions.force) {
(errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"));
errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"));
}
if (buildOptions.clean && buildOptions.verbose) {
(errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose"));
errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose"));
}
if (buildOptions.clean && buildOptions.watch) {
(errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch"));
errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch"));
}
if (buildOptions.watch && buildOptions.dry) {
(errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry"));
errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry"));
}
return { buildOptions, projects, errors: errors || emptyArray };
return { buildOptions, projects, errors };
}
function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string {
+9 -6
View File
@@ -2948,7 +2948,10 @@
"category": "Error",
"code": 5072
},
"Build option '{0}' requires a value of type {1}.": {
"category": "Error",
"code": 5073
},
"Generates a sourcemap for each corresponding '.d.ts' file.": {
"category": "Message",
@@ -4640,7 +4643,7 @@
"category": "Message",
"code": 95062
},
"Add missing enum member '{0}'": {
"category": "Message",
"code": 95063
@@ -4649,12 +4652,12 @@
"category": "Message",
"code": 95064
},
"Convert to async function":{
"Convert to async function": {
"category": "Message",
"code": 95065
"code": 95065
},
"Convert all to async functions": {
"category": "Message",
"code": 95066
"category": "Message",
"code": 95066
}
}
+37 -17
View File
@@ -17,14 +17,18 @@ namespace ts {
referencingProjectsMap: ConfigFileMap<ConfigFileMap<boolean>>;
}
export interface BuildOptions {
export interface BuildOptions extends OptionsBase {
dry?: boolean;
force?: boolean;
verbose?: boolean;
/*@internal*/ clean?: boolean;
/*@internal*/ watch?: boolean;
/*@internal*/ help?: boolean;
preserveWatchOutput?: boolean;
listEmittedFiles?: boolean;
listFiles?: boolean;
}
enum BuildResultFlags {
@@ -44,8 +48,9 @@ namespace ts {
SyntaxErrors = 1 << 3,
TypeErrors = 1 << 4,
DeclarationEmitErrors = 1 << 5,
EmitErrors = 1 << 6,
AnyErrors = ConfigFileErrors | SyntaxErrors | TypeErrors | DeclarationEmitErrors
AnyErrors = ConfigFileErrors | SyntaxErrors | TypeErrors | DeclarationEmitErrors | EmitErrors
}
export enum UpToDateStatusType {
@@ -370,6 +375,14 @@ namespace ts {
return host;
}
function getCompilerOptionsOfBuildOptions(buildOptions: BuildOptions): CompilerOptions {
const result = {} as CompilerOptions;
commonOptionsWithBuild.forEach(option => {
result[option.name] = buildOptions[option.name];
});
return result;
}
/**
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
* can dynamically add/remove other projects based on changes on the rootNames' references
@@ -384,6 +397,7 @@ namespace ts {
// State of the solution
let options = defaultOptions;
let baseCompilerOptions = getCompilerOptionsOfBuildOptions(options);
type ConfigFileCacheEntry = ParsedCommandLine | Diagnostic;
const configFileCache = createFileMap<ConfigFileCacheEntry>(toPath);
/** Map from output file name to its pre-build timestamp */
@@ -392,6 +406,7 @@ namespace ts {
const projectStatus = createFileMap<UpToDateStatus>(toPath);
const missingRoots = createMap<true>();
let globalDependencyGraph: DependencyGraph | undefined;
const writeFileName = (s: string) => host.trace && host.trace(s);
// Watch state
const diagnostics = createFileMap<ReadonlyArray<Diagnostic>>(toPath);
@@ -430,6 +445,7 @@ namespace ts {
function resetBuildContext(opts = defaultOptions) {
options = opts;
baseCompilerOptions = getCompilerOptionsOfBuildOptions(options);
configFileCache.clear();
unchangedOutputs.clear();
projectStatus.clear();
@@ -463,7 +479,7 @@ namespace ts {
let diagnostic: Diagnostic | undefined;
parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = d => diagnostic = d;
const parsed = getParsedCommandLineOfConfigFile(configFilePath, {}, parseConfigFileHost);
const parsed = getParsedCommandLineOfConfigFile(configFilePath, baseCompilerOptions, parseConfigFileHost);
parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = noop;
configFileCache.setValue(configFilePath, parsed || diagnostic!);
return parsed;
@@ -475,7 +491,7 @@ namespace ts {
function reportWatchStatus(message: DiagnosticMessage, ...args: (string | number | undefined)[]) {
if (hostWithWatch.onWatchStatusChange) {
hostWithWatch.onWatchStatusChange(createCompilerDiagnostic(message, ...args), host.getNewLine(), { preserveWatchOutput: options.preserveWatchOutput });
hostWithWatch.onWatchStatusChange(createCompilerDiagnostic(message, ...args), host.getNewLine(), baseCompilerOptions);
}
}
@@ -1004,35 +1020,28 @@ namespace ts {
...program.getConfigFileParsingDiagnostics(),
...program.getSyntacticDiagnostics()];
if (syntaxDiagnostics.length) {
resultFlags |= BuildResultFlags.SyntaxErrors;
reportAndStoreErrors(proj, syntaxDiagnostics);
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" });
return resultFlags;
return buildErrors(syntaxDiagnostics, BuildResultFlags.SyntaxErrors, "Syntactic");
}
// Don't emit .d.ts if there are decl file errors
if (getEmitDeclarations(program.getCompilerOptions())) {
const declDiagnostics = program.getDeclarationDiagnostics();
if (declDiagnostics.length) {
resultFlags |= BuildResultFlags.DeclarationEmitErrors;
reportAndStoreErrors(proj, declDiagnostics);
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" });
return resultFlags;
return buildErrors(declDiagnostics, BuildResultFlags.DeclarationEmitErrors, "Declaration file");
}
}
// Same as above but now for semantic diagnostics
const semanticDiagnostics = program.getSemanticDiagnostics();
if (semanticDiagnostics.length) {
resultFlags |= BuildResultFlags.TypeErrors;
reportAndStoreErrors(proj, semanticDiagnostics);
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" });
return resultFlags;
return buildErrors(semanticDiagnostics, BuildResultFlags.TypeErrors, "Semantic");
}
let newestDeclarationFileContentChangedTime = minimumDate;
let anyDtsChanged = false;
program.emit(/*targetSourceFile*/ undefined, (fileName, content, writeBom, onError) => {
let emitDiagnostics: Diagnostic[] | undefined;
const reportEmitDiagnostic = (d: Diagnostic) => (emitDiagnostics || (emitDiagnostics = [])).push(d);
emitFilesAndReportErrors(program, reportEmitDiagnostic, writeFileName, /*reportSummary*/ undefined, (fileName, content, writeBom, onError) => {
let priorChangeTime: Date | undefined;
if (!anyDtsChanged && isDeclarationFile(fileName)) {
// Check for unchanged .d.ts files
@@ -1052,12 +1061,23 @@ namespace ts {
}
});
if (emitDiagnostics) {
return buildErrors(emitDiagnostics, BuildResultFlags.EmitErrors, "Emit");
}
const status: UpToDateStatus = {
type: UpToDateStatusType.UpToDate,
newestDeclarationFileContentChangedTime: anyDtsChanged ? maximumDate : newestDeclarationFileContentChangedTime
};
projectStatus.setValue(proj, status);
return resultFlags;
function buildErrors(diagnostics: ReadonlyArray<Diagnostic>, errorFlags: BuildResultFlags, errorType: string) {
resultFlags |= errorFlags;
reportAndStoreErrors(proj, diagnostics);
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: `${errorType} errors` });
return resultFlags;
}
}
function updateOutputTimestamps(proj: ParsedCommandLine) {
+3 -3
View File
@@ -101,7 +101,7 @@ namespace ts {
getGlobalDiagnostics(): ReadonlyArray<Diagnostic>;
getSemanticDiagnostics(): ReadonlyArray<Diagnostic>;
getConfigFileParsingDiagnostics(): ReadonlyArray<Diagnostic>;
emit(): EmitResult;
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
}
export type ReportEmitErrorSummary = (errorCount: number) => void;
@@ -109,7 +109,7 @@ namespace ts {
/**
* Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options
*/
export function emitFilesAndReportErrors(program: ProgramToEmitFilesAndReportErrors, reportDiagnostic: DiagnosticReporter, writeFileName?: (s: string) => void, reportSummary?: ReportEmitErrorSummary) {
export function emitFilesAndReportErrors(program: ProgramToEmitFilesAndReportErrors, reportDiagnostic: DiagnosticReporter, writeFileName?: (s: string) => void, reportSummary?: ReportEmitErrorSummary, writeFile?: WriteFileCallback) {
// First get and report any syntactic errors.
const diagnostics = program.getConfigFileParsingDiagnostics().slice();
const configFileParsingDiagnosticsLength = diagnostics.length;
@@ -128,7 +128,7 @@ namespace ts {
}
// Emit and report any errors we ran into.
const { emittedFiles, emitSkipped, diagnostics: emitDiagnostics } = program.emit();
const { emittedFiles, emitSkipped, diagnostics: emitDiagnostics } = program.emit(/*targetSourceFile*/ undefined, writeFile);
addRange(diagnostics, emitDiagnostics);
if (reportSemanticDiagnostics) {
+57
View File
@@ -264,6 +264,63 @@ export class cNew {}`);
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withIncludeAndFiles.json");
});
});
describe("tsbuild - lists files", () => {
it("listFiles", () => {
const fs = projFs.shadow();
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/tests"], { listFiles: true });
builder.buildAllProjects();
assert.deepEqual(host.traces, [
...getLibs(),
"/src/core/anotherModule.ts",
"/src/core/index.ts",
"/src/core/some_decl.d.ts",
...getLibs(),
...getCoreOutputs(),
"/src/logic/index.ts",
...getLibs(),
...getCoreOutputs(),
"/src/logic/index.d.ts",
"/src/tests/index.ts"
]);
function getLibs() {
return [
"/lib/lib.d.ts",
"/lib/lib.es5.d.ts",
"/lib/lib.dom.d.ts",
"/lib/lib.webworker.importscripts.d.ts",
"/lib/lib.scripthost.d.ts"
];
}
function getCoreOutputs() {
return [
"/src/core/index.d.ts",
"/src/core/anotherModule.d.ts"
];
}
});
it("listEmittedFiles", () => {
const fs = projFs.shadow();
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/tests"], { listEmittedFiles: true });
builder.buildAllProjects();
assert.deepEqual(host.traces, [
"TSFILE: /src/core/anotherModule.js",
"TSFILE: /src/core/anotherModule.d.ts",
"TSFILE: /src/core/index.js",
"TSFILE: /src/core/index.d.ts",
"TSFILE: /src/logic/index.js",
"TSFILE: /src/logic/index.js.map",
"TSFILE: /src/logic/index.d.ts",
"TSFILE: /src/tests/index.js",
"TSFILE: /src/tests/index.d.ts",
]);
});
});
}
export namespace OutFile {
+34 -24
View File
@@ -2,7 +2,7 @@ namespace ts.tscWatch {
export import libFile = TestFSWithWatch.libFile;
function createSolutionBuilder(system: WatchedSystem, rootNames: ReadonlyArray<string>, defaultOptions?: BuildOptions) {
const host = createSolutionBuilderWithWatchHost(system);
return ts.createSolutionBuilder(host, rootNames, defaultOptions || { dry: false, force: false, verbose: false, watch: true });
return ts.createSolutionBuilder(host, rootNames, defaultOptions || { watch: true });
}
function createSolutionBuilderWithWatch(host: WatchedSystem, rootNames: ReadonlyArray<string>, defaultOptions?: BuildOptions) {
@@ -95,11 +95,11 @@ namespace ts.tscWatch {
const allFiles: ReadonlyArray<File> = [libFile, ...core, ...logic, ...tests, ...ui];
const testProjectExpectedWatchedFiles = [core[0], core[1], core[2], ...logic, ...tests].map(f => f.path);
function createSolutionInWatchMode(allFiles: ReadonlyArray<File>) {
function createSolutionInWatchMode(allFiles: ReadonlyArray<File>, defaultOptions?: BuildOptions, disableConsoleClears?: boolean) {
const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation });
createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]);
createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`], defaultOptions);
verifyWatches(host);
checkOutputErrorsInitial(host, emptyArray);
checkOutputErrorsInitial(host, emptyArray, disableConsoleClears);
const outputFileStamps = getOutputFileStamps(host);
for (const stamp of outputFileStamps) {
assert.isDefined(stamp[1], `${stamp[0]} expected to be present`);
@@ -351,32 +351,42 @@ function myFunc() { return 100; }`);
}
});
it("reports errors in all projects on incremental compile", () => {
const host = createSolutionInWatchMode(allFiles);
const outputFileStamps = getOutputFileStamps(host);
describe("reports errors in all projects on incremental compile", () => {
function verifyIncrementalErrors(defaultBuildOptions?: BuildOptions, disabledConsoleClear?: boolean) {
const host = createSolutionInWatchMode(allFiles, defaultBuildOptions, disabledConsoleClear);
const outputFileStamps = getOutputFileStamps(host);
host.writeFile(logic[1].path, `${logic[1].content}
host.writeFile(logic[1].path, `${logic[1].content}
let y: string = 10;`);
host.checkTimeoutQueueLengthAndRun(1); // Builds logic
const changedLogic = getOutputFileStamps(host);
verifyChangedFiles(changedLogic, outputFileStamps, emptyArray);
host.checkTimeoutQueueLength(0);
checkOutputErrorsIncremental(host, [
`sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n`
]);
host.checkTimeoutQueueLengthAndRun(1); // Builds logic
const changedLogic = getOutputFileStamps(host);
verifyChangedFiles(changedLogic, outputFileStamps, emptyArray);
host.checkTimeoutQueueLength(0);
checkOutputErrorsIncremental(host, [
`sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n`
], disabledConsoleClear);
host.writeFile(core[1].path, `${core[1].content}
host.writeFile(core[1].path, `${core[1].content}
let x: string = 10;`);
host.checkTimeoutQueueLengthAndRun(1); // Builds core
const changedCore = getOutputFileStamps(host);
verifyChangedFiles(changedCore, changedLogic, emptyArray);
host.checkTimeoutQueueLength(0);
checkOutputErrorsIncremental(host, [
`sample1/core/index.ts(5,5): error TS2322: Type '10' is not assignable to type 'string'.\n`,
`sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n`
]);
host.checkTimeoutQueueLengthAndRun(1); // Builds core
const changedCore = getOutputFileStamps(host);
verifyChangedFiles(changedCore, changedLogic, emptyArray);
host.checkTimeoutQueueLength(0);
checkOutputErrorsIncremental(host, [
`sample1/core/index.ts(5,5): error TS2322: Type '10' is not assignable to type 'string'.\n`,
`sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n`
], disabledConsoleClear);
}
it("when preserveWatchOutput is not used", () => {
verifyIncrementalErrors();
});
it("when preserveWatchOutput is passed on command line", () => {
verifyIncrementalErrors({ preserveWatchOutput: true, watch: true }, /*disabledConsoleClear*/ true);
});
});
// TODO: write tests reporting errors but that will have more involved work since file
});
+12 -17
View File
@@ -53,14 +53,10 @@ namespace ts {
}
export function executeCommandLine(args: string[]): void {
if (args.length > 0 && ((args[0].toLowerCase() === "--build") || (args[0].toLowerCase() === "-b"))) {
const result = performBuild(args.slice(1));
// undefined = in watch mode, do not exit
if (result !== undefined) {
return sys.exit(result);
}
else {
return;
if (args.length > 0 && args[0].charCodeAt(0) === CharacterCodes.minus) {
const firstOption = args[0].slice(args[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
if (firstOption === "build" || firstOption === "b") {
return performBuild(args.slice(1));
}
}
@@ -164,17 +160,17 @@ namespace ts {
}
}
function performBuild(args: string[]): number | undefined {
function performBuild(args: string[]) {
const { buildOptions, projects, errors } = parseBuildCommand(args);
if (errors.length > 0) {
errors.forEach(reportDiagnostic);
return ExitStatus.DiagnosticsPresent_OutputsSkipped;
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
if (buildOptions.help) {
printVersion();
printHelp(buildOpts, "--build ");
return ExitStatus.Success;
return sys.exit(ExitStatus.Success);
}
// Update to pretty if host supports it
@@ -182,12 +178,12 @@ namespace ts {
if (projects.length === 0) {
printVersion();
printHelp(buildOpts, "--build ");
return ExitStatus.Success;
return sys.exit(ExitStatus.Success);
}
if (!sys.getModifiedTime || !sys.setModifiedTime || (buildOptions.clean && !sys.deleteFile)) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build"));
return ExitStatus.DiagnosticsPresent_OutputsSkipped;
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
if (buildOptions.watch) {
reportWatchModeWithoutSysSupport();
@@ -196,16 +192,15 @@ namespace ts {
// TODO: change this to host if watch => watchHost otherwiue without wathc
const builder = createSolutionBuilder(createSolutionBuilderWithWatchHost(sys, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty()), createWatchStatusReporter()), projects, buildOptions);
if (buildOptions.clean) {
return builder.cleanAllProjects();
return sys.exit(builder.cleanAllProjects());
}
if (buildOptions.watch) {
builder.buildAllProjects();
builder.startWatching();
return undefined;
return builder.startWatching();
}
return builder.buildAllProjects();
return sys.exit(builder.buildAllProjects());
}
function performCompilation(rootNames: string[], projectReferences: ReadonlyArray<ProjectReference> | undefined, options: CompilerOptions, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) {