mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-24 02:21:30 -05:00
Refactor config file syntax search to callback model instead of constructing arrays to iterate over (#53416)
This commit is contained in:
@@ -41,11 +41,11 @@ import {
|
||||
filterMutate,
|
||||
find,
|
||||
findIndex,
|
||||
firstDefined,
|
||||
firstOrUndefinedIterator,
|
||||
flatten,
|
||||
forEach,
|
||||
forEachEntry,
|
||||
forEachTsConfigPropArray,
|
||||
getBaseFileName,
|
||||
getDirectoryPath,
|
||||
getFileMatcherPatterns,
|
||||
@@ -59,7 +59,6 @@ import {
|
||||
getSupportedExtensions,
|
||||
getSupportedExtensionsWithJsonIfResolveJsonModule,
|
||||
getTextOfPropertyName,
|
||||
getTsConfigPropArray,
|
||||
getTsConfigPropArrayElementValue,
|
||||
hasExtension,
|
||||
hasProperty,
|
||||
@@ -2886,7 +2885,7 @@ function parseJsonConfigFileContentWorker(
|
||||
if (sourceFile) {
|
||||
const fileName = configFileName || "tsconfig.json";
|
||||
const diagnosticMessage = Diagnostics.The_files_list_in_config_file_0_is_empty;
|
||||
const nodeValue = firstDefined(getTsConfigPropArray(sourceFile, "files"), property => property.initializer);
|
||||
const nodeValue = forEachTsConfigPropArray(sourceFile, "files", property => property.initializer);
|
||||
const error = createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, nodeValue, diagnosticMessage, fileName);
|
||||
errors.push(error);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,6 @@ import {
|
||||
filter,
|
||||
find,
|
||||
findIndex,
|
||||
firstDefined,
|
||||
firstDefinedIterator,
|
||||
flatMap,
|
||||
flatten,
|
||||
@@ -104,7 +103,9 @@ import {
|
||||
forEachEmittedFile,
|
||||
forEachEntry,
|
||||
forEachKey,
|
||||
forEachPropertyAssignment,
|
||||
forEachResolvedProjectReference as ts_forEachResolvedProjectReference,
|
||||
forEachTsConfigPropArray,
|
||||
FunctionLikeDeclaration,
|
||||
getAllowJSCompilerOption,
|
||||
getAutomaticTypeDirectiveNames,
|
||||
@@ -138,7 +139,6 @@ import {
|
||||
getPathFromPathComponents,
|
||||
getPositionOfLineAndCharacter,
|
||||
getPropertyArrayElementValue,
|
||||
getPropertyAssignment,
|
||||
getResolvedModule,
|
||||
getResolveJsonModule,
|
||||
getRootLength,
|
||||
@@ -152,7 +152,6 @@ import {
|
||||
getTransformers,
|
||||
getTsBuildInfoEmitOutputFilePath,
|
||||
getTsConfigObjectLiteralExpression,
|
||||
getTsConfigPropArray,
|
||||
getTsConfigPropArrayElementValue,
|
||||
HasChangedAutomaticTypeDirectiveNames,
|
||||
hasChangesInResolutions,
|
||||
@@ -263,6 +262,7 @@ import {
|
||||
ProjectReference,
|
||||
ProjectReferenceFile,
|
||||
projectReferenceIsEqualTo,
|
||||
PropertyAssignment,
|
||||
PropertyDeclaration,
|
||||
ReferencedFile,
|
||||
removeFileExtension,
|
||||
@@ -4535,7 +4535,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
);
|
||||
if (!referenceInfo) return undefined;
|
||||
const { sourceFile, index } = referenceInfo;
|
||||
const referencesSyntax = firstDefined(getTsConfigPropArray(sourceFile as TsConfigSourceFile, "references"),
|
||||
const referencesSyntax = forEachTsConfigPropArray(sourceFile as TsConfigSourceFile, "references",
|
||||
property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined);
|
||||
return referencesSyntax && referencesSyntax.elements.length > index ?
|
||||
createDiagnosticForNodeInSourceFile(
|
||||
@@ -4610,19 +4610,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
|
||||
function createDiagnosticForOptionPathKeyValue(key: string, valueIndex: number, message: DiagnosticMessage, ...args: DiagnosticArguments) {
|
||||
let needCompilerDiagnostic = true;
|
||||
const pathsSyntax = getOptionPathsSyntax();
|
||||
for (const pathProp of pathsSyntax) {
|
||||
forEachOptionPathsSyntax(pathProp => {
|
||||
if (isObjectLiteralExpression(pathProp.initializer)) {
|
||||
for (const keyProps of getPropertyAssignment(pathProp.initializer, key)) {
|
||||
forEachPropertyAssignment(pathProp.initializer, key, keyProps => {
|
||||
const initializer = keyProps.initializer;
|
||||
if (isArrayLiteralExpression(initializer) && initializer.elements.length > valueIndex) {
|
||||
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, initializer.elements[valueIndex], message, ...args));
|
||||
needCompilerDiagnostic = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
if (needCompilerDiagnostic) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(message, ...args));
|
||||
}
|
||||
@@ -4630,32 +4628,29 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
|
||||
function createDiagnosticForOptionPaths(onKey: boolean, key: string, message: DiagnosticMessage, ...args: DiagnosticArguments) {
|
||||
let needCompilerDiagnostic = true;
|
||||
const pathsSyntax = getOptionPathsSyntax();
|
||||
for (const pathProp of pathsSyntax) {
|
||||
forEachOptionPathsSyntax(pathProp => {
|
||||
if (isObjectLiteralExpression(pathProp.initializer) &&
|
||||
createOptionDiagnosticInObjectLiteralSyntax(
|
||||
pathProp.initializer, onKey, key, /*key2*/ undefined,
|
||||
message, ...args)) {
|
||||
needCompilerDiagnostic = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (needCompilerDiagnostic) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(message, ...args));
|
||||
}
|
||||
}
|
||||
|
||||
function getOptionsSyntaxByName(name: string) {
|
||||
const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax();
|
||||
return compilerOptionsObjectLiteralSyntax && getPropertyAssignment(compilerOptionsObjectLiteralSyntax, name);
|
||||
function forEachOptionsSyntaxByName<T>(name: string, callback: (prop: PropertyAssignment) => T | undefined): T | undefined {
|
||||
return forEachPropertyAssignment(getCompilerOptionsObjectLiteralSyntax(), name, callback);
|
||||
}
|
||||
|
||||
function getOptionPathsSyntax() {
|
||||
return getOptionsSyntaxByName("paths") || emptyArray;
|
||||
function forEachOptionPathsSyntax<T>(callback: (prop: PropertyAssignment) => T | undefined) {
|
||||
return forEachOptionsSyntaxByName("paths", callback);
|
||||
}
|
||||
|
||||
function getOptionsSyntaxByValue(name: string, value: string) {
|
||||
const syntaxByName = getOptionsSyntaxByName(name);
|
||||
return syntaxByName && firstDefined(syntaxByName, property => isStringLiteral(property.initializer) && property.initializer.text === value ? property.initializer : undefined);
|
||||
return forEachOptionsSyntaxByName(name, property => isStringLiteral(property.initializer) && property.initializer.text === value ? property.initializer : undefined);
|
||||
}
|
||||
|
||||
function getOptionsSyntaxByArrayElementValue(name: string, value: string) {
|
||||
@@ -4673,7 +4668,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
}
|
||||
|
||||
function createDiagnosticForReference(sourceFile: JsonSourceFile | undefined, index: number, message: DiagnosticMessage, ...args: DiagnosticArguments) {
|
||||
const referencesSyntax = firstDefined(getTsConfigPropArray(sourceFile || options.configFile, "references"),
|
||||
const referencesSyntax = forEachTsConfigPropArray(sourceFile || options.configFile, "references",
|
||||
property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined);
|
||||
if (referencesSyntax && referencesSyntax.elements.length > index) {
|
||||
programDiagnostics.add(createDiagnosticForNodeInSourceFile(sourceFile || options.configFile!, referencesSyntax.elements[index], message, ...args));
|
||||
@@ -4703,16 +4698,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
|
||||
function getCompilerOptionsObjectLiteralSyntax() {
|
||||
if (_compilerOptionsObjectLiteralSyntax === undefined) {
|
||||
_compilerOptionsObjectLiteralSyntax = false;
|
||||
const jsonObjectLiteral = getTsConfigObjectLiteralExpression(options.configFile);
|
||||
if (jsonObjectLiteral) {
|
||||
for (const prop of getPropertyAssignment(jsonObjectLiteral, "compilerOptions")) {
|
||||
if (isObjectLiteralExpression(prop.initializer)) {
|
||||
_compilerOptionsObjectLiteralSyntax = prop.initializer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_compilerOptionsObjectLiteralSyntax = forEachPropertyAssignment(
|
||||
getTsConfigObjectLiteralExpression(options.configFile),
|
||||
"compilerOptions",
|
||||
prop => isObjectLiteralExpression(prop.initializer) ? prop.initializer : undefined
|
||||
) || false;
|
||||
}
|
||||
return _compilerOptionsObjectLiteralSyntax || undefined;
|
||||
}
|
||||
@@ -4721,8 +4711,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments): boolean;
|
||||
function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage | DiagnosticMessageChain, ...args: DiagnosticArguments): boolean;
|
||||
function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage | DiagnosticMessageChain, ...args: DiagnosticArguments): boolean {
|
||||
const props = getPropertyAssignment(objectLiteral, key1, key2);
|
||||
for (const prop of props) {
|
||||
let needsCompilerDiagnostic = false;
|
||||
forEachPropertyAssignment(objectLiteral, key1, prop => {
|
||||
// eslint-disable-next-line local/no-in-operator
|
||||
if ("messageText" in message) {
|
||||
programDiagnostics.add(createDiagnosticForNodeFromMessageChain(options.configFile!, onKey ? prop.name : prop.initializer, message));
|
||||
@@ -4730,8 +4720,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
else {
|
||||
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, onKey ? prop.name : prop.initializer, message, ...args));
|
||||
}
|
||||
}
|
||||
return !!props.length;
|
||||
needsCompilerDiagnostic = true;
|
||||
}, key2);
|
||||
return needsCompilerDiagnostic;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2683,22 +2683,23 @@ export function isThisTypePredicate(predicate: TypePredicate): predicate is This
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getPropertyAssignment(objectLiteral: ObjectLiteralExpression, key: string, key2?: string): readonly PropertyAssignment[] {
|
||||
return objectLiteral.properties.filter((property): property is PropertyAssignment => {
|
||||
if (property.kind === SyntaxKind.PropertyAssignment) {
|
||||
const propName = tryGetTextOfPropertyName(property.name);
|
||||
return key === propName || (!!key2 && key2 === propName);
|
||||
}
|
||||
return false;
|
||||
export function forEachPropertyAssignment<T>(objectLiteral: ObjectLiteralExpression | undefined, key: string, callback: (property: PropertyAssignment) => T | undefined, key2?: string) {
|
||||
return forEach(objectLiteral?.properties, property => {
|
||||
if (!isPropertyAssignment(property)) return undefined;
|
||||
const propName = tryGetTextOfPropertyName(property.name);
|
||||
return key === propName || (key2 && key2 === propName) ?
|
||||
callback(property) :
|
||||
undefined;
|
||||
});
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getPropertyArrayElementValue(objectLiteral: ObjectLiteralExpression, propKey: string, elementValue: string): StringLiteral | undefined {
|
||||
return firstDefined(getPropertyAssignment(objectLiteral, propKey), property =>
|
||||
return forEachPropertyAssignment(objectLiteral, propKey, property =>
|
||||
isArrayLiteralExpression(property.initializer) ?
|
||||
find(property.initializer.elements, (element): element is StringLiteral => isStringLiteral(element) && element.text === elementValue) :
|
||||
undefined);
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -2711,16 +2712,15 @@ export function getTsConfigObjectLiteralExpression(tsConfigSourceFile: TsConfigS
|
||||
|
||||
/** @internal */
|
||||
export function getTsConfigPropArrayElementValue(tsConfigSourceFile: TsConfigSourceFile | undefined, propKey: string, elementValue: string): StringLiteral | undefined {
|
||||
return firstDefined(getTsConfigPropArray(tsConfigSourceFile, propKey), property =>
|
||||
return forEachTsConfigPropArray(tsConfigSourceFile, propKey, property =>
|
||||
isArrayLiteralExpression(property.initializer) ?
|
||||
find(property.initializer.elements, (element): element is StringLiteral => isStringLiteral(element) && element.text === elementValue) :
|
||||
undefined);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getTsConfigPropArray(tsConfigSourceFile: TsConfigSourceFile | undefined, propKey: string): readonly PropertyAssignment[] {
|
||||
const jsonObjectLiteral = getTsConfigObjectLiteralExpression(tsConfigSourceFile);
|
||||
return jsonObjectLiteral ? getPropertyAssignment(jsonObjectLiteral, propKey) : emptyArray;
|
||||
export function forEachTsConfigPropArray<T>(tsConfigSourceFile: TsConfigSourceFile | undefined, propKey: string, callback: (property: PropertyAssignment) => T | undefined) {
|
||||
return forEachPropertyAssignment(getTsConfigObjectLiteralExpression(tsConfigSourceFile), propKey, callback);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
Reference in New Issue
Block a user