mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-24 04:30:53 -06:00
Unify the commandline parsing worker
This commit is contained in:
parent
37c3c5d8bb
commit
0d60348e45
@ -62,7 +62,8 @@ namespace ts {
|
||||
/* @internal */
|
||||
export const libMap = createMapFromEntries(libEntries);
|
||||
|
||||
const commonOptionsWithBuild: CommandLineOption[] = [
|
||||
/* @internal */
|
||||
export const commonOptionsWithBuild: CommandLineOption[] = [
|
||||
{
|
||||
name: "help",
|
||||
shortName: "h",
|
||||
@ -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<T extends OptionsBase>(
|
||||
getOptionNameMap: () => OptionNameMap,
|
||||
[unknownOptionDiagnostic, optionTypeMismatchDiagnostic]: ParseCommandLineWorkerDiagnostics,
|
||||
commandLine: ReadonlyArray<string>,
|
||||
readFile?: (path: string) => string | undefined) {
|
||||
const options = {} as T;
|
||||
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,10 @@ 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: buildOptions, fileNames: projects, errors } = parseCommandLineWorker<BuildOptions>(returnBuildOptionNameMap, [
|
||||
Diagnostics.Unknown_build_option_0,
|
||||
Diagnostics.Build_option_0_requires_a_value_of_type_1
|
||||
], args);
|
||||
|
||||
if (projects.length === 0) {
|
||||
// tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
|
||||
@ -1071,19 +1073,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 {
|
||||
|
||||
@ -2920,7 +2920,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",
|
||||
@ -4604,7 +4607,7 @@
|
||||
"category": "Message",
|
||||
"code": 95062
|
||||
},
|
||||
|
||||
|
||||
"Add missing enum member '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 95063
|
||||
@ -4613,12 +4616,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
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ namespace ts {
|
||||
referencingProjectsMap: ConfigFileMap<ConfigFileMap<boolean>>;
|
||||
}
|
||||
|
||||
export interface BuildOptions {
|
||||
export interface BuildOptions extends OptionsBase {
|
||||
dry?: boolean;
|
||||
force?: boolean;
|
||||
verbose?: boolean;
|
||||
@ -370,6 +370,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 +392,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 */
|
||||
@ -430,6 +439,7 @@ namespace ts {
|
||||
|
||||
function resetBuildContext(opts = defaultOptions) {
|
||||
options = opts;
|
||||
baseCompilerOptions = getCompilerOptionsOfBuildOptions(options);
|
||||
configFileCache.clear();
|
||||
unchangedOutputs.clear();
|
||||
projectStatus.clear();
|
||||
@ -463,7 +473,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 +485,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user